powershellstreamstdout

How to capture ProcessStartInfo stdout as a string for comparison, with Powershell?


I'm getting the output of

T h i s a c t i o n i s o n l y v a l i d f o r p r o d u c t s t h a t a r e c u r r e n t l y i n s t a l l e d .

and would like to test for that condition as well as others, however $stdout gettype is a string, but when I test for $stdout -eq $null or $stdout -eq the quote above, it always fails. Does the stream have to be converted somehow? How can I do comparisons with $null and other strings?

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = 'msiexec'
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "/x {22AD1D41-EDA0-4387-BF16-9045CE734FAD} /quiet /norestart /l*v `"C:\temp\msi123_MSI_UNINSTALL.log`""
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd() | Out-String
$stderr = $p.StandardError.ReadToEnd()

Solution

  • msiexec.exe is unusual in several respects:


    If you simply want to know whether any stdout or stderr was produced, the simplest approach is to take advantage of PowerShell's implicit to-Boolean coercions, which treat both $null and the empty string as $false:

    if (-not $stdout) { 'No stdout output was produced.' }
    

    Read on for how to properly decode the messages returned so you can do string comparisons, as well as for a better way to determine success vs. failure.


    If you do want to examine the specific stdout (and, hypothetically, stderr) output, you must decode it properly:

    $pinfo = [System.Diagnostics.ProcessStartInfo] @{
      FileName = 'msiexec'
      Arguments = "/x {22AD1D41-EDA0-4387-BF16-9045CE734FAD} /quiet /norestart /l*v `"C:\temp\msi123_MSI_UNINSTALL.log`""
      UseShellExecute = $false
      RedirectStandardError = $true
      RedirectStandardOutput = $true
      StandardOutputEncoding = [System.Text.Encoding]::Unicode
      StandardErrorEncoding = [System.Text.Encoding]::Unicode
    }
    $p = [System.Diagnostics.Process]::Start($pinfo)
    $p.WaitForExit()
    $stdout = $p.StandardOutput.ReadToEnd()
    $stderr = $p.StandardError.ReadToEnd()
    

    Note: