0

As a PowerShell newbie, I've finally been able to write a PowerShell script to patch my Delphi projects files. There is just one weird thing : Powershell Outputs a string that is used as an argument to a method call :

function PatchProject($ProjectFile) {
  # Write-Host "Processing " $ProjectFile

  [xml]$xml = Get-Content -Path $ProjectFile

  # We need a XmlNamespaceManager to process XPath Queries
  [System.Xml.XmlNamespaceManager] $nsm = New-Object System.Xml.XmlNamespaceManager $xml.NameTable
  $nsm.AddNamespace("ns", "http://schemas.microsoft.com/developer/msbuild/2003");

  $changed = $false

  If ($xml.Project.SelectSingleNode('ns:PropertyGroup[not(@Condition)]/ns:MyProjectRoot', $nsm) -eq $null) {

    # Create new variable node
    $my_root = $xml.CreateElement('MyProjectRoot', $xml.Project.NamespaceURI)

    ###########
    ###########
    $my_root.set_InnerText('P:\MyProject') # "P:\MyProject" is printed on the console, why ?!?
    ###########
    ###########

    # Find first <PropertyGroup> and append <MyProjectRoot>...</MyProjectRoot> to it
    $pg = $xml.Project.SelectSingleNode('ns:PropertyGroup[not(@Condition)]', $nsm);
    $pg.AppendChild($my_root)

    $changed = $true
  }

  If ($xml.Project.SelectSingleNode('ns:Import[@Project="$(MyProjectRoot)\ide\Delphi.VersionInfo.targets"]', $nsm) -eq $null) {

    # Add a node <Import Project="..." Condition="..." />
    $import = $xml.CreateElement('Import', $xml.Project.NamespaceURI)
    $import.SetAttribute('Condition', "`$(FileVersion)!='' and Exists('`$(MyProjectRoot)\ide\Delphi.VersionInfo.targets')")
    $import.SetAttribute('Project', "`$(MyProjectRoot)\ide\Delphi.VersionInfo.targets")

    # Find last <Import .../>
    $last_import = $xml.Project.SelectSingleNode('ns:Import[last()]', $nsm)

    # Insert this node after the very last <Import... />
    $xml.Project.InsertAfter($import, $last_import)

    $changed = $true
  }

  If ($changed -eq $true) {

    # Set Project MSBUILD ToolsVersion
    $xml.Project.SetAttribute('ToolsVersion', '4.0')

    # Write preserving Delphi indentation settings
    $settings = New-Object System.Xml.XmlWriterSettings
    $settings.OmitXmlDeclaration = $true
    $settings.Indent = $true
    $settings.IndentChars = "    "

    $writer = [System.XML.XmlWriter]::Create($ProjectFile, $settings)

    $xml.Save($writer)
    $writer.Close()
    
    $xml = $null
    
    # Reformat file to match Delphi syntax
    $lines=@(Get-Content -Path $ProjectFile)
    $newlines = @()
    foreach ($line in $lines) {
      $new_line = $line -Replace " />", "/>"
      $newlines += $new_line
    }
    $newlines | Set-Content -Encoding UTF8 -Path $ProjectFile 
    
  }

  # Write-Host "Processed " $ProjectFile
}

Write-Host "Finding .dproj..."
$files = Get-ChildItem -Path .\ -Filter *.dproj -Recurse -File -Name

Write-Host "Patching .dproj..."
$files | ForEach-Object { PatchProject $_ }

The same unwanted output happens when I use the InnerText property instead of the set_InnerText() accessor.

$my_root.InnerText = 'P:\MyProject'

I upgraded my PowerShell to version 7.1.

I'm wondering whether it could be a debug output from System.Xml.Element.set_InnerText()... ? Or is this a known side effect of PowerShell ? Or did I missed something ?

Solution

As explained in comments the solution is to suppress implicit output by assigning this method call into $null :

$null = $my_root.set_InnerText('P:\MyProject')
Ken White
  • 123,280
  • 14
  • 225
  • 444
ZeDalaye
  • 689
  • 7
  • 17
  • If you don't want a particular output you can pipe it to `Out-Null`, you can assign it to a variable or you use the [VOID] statement to *hide* the output. – Olaf Nov 29 '20 at 22:58
  • 2
    In short: any output - be it from a command or a .NET method call - that is neither captured nor redirected (sent through the pipeline or to a file) is _implicitly output_. To simply _discard_ such output, it's best to use `$null = ...`; see [this answer](https://stackoverflow.com/a/55665963/45375). – mklement0 Nov 29 '20 at 23:05
  • I've removed the Delphi tag, as your question has nothing to do with Delphi. Please use only tags that are actually relevant to your post. Tags have meaning and relevance here, and misuse is not helpful. The fact your Powershell code patches something you wrote in Delphi is not relevant to the question here. – Ken White Nov 30 '20 at 02:59

0 Answers0