0

I'm trying to process the output of a Process using a job because I need it to be parallel but the System.IO.StreamReader turns into a Deserialized.System.IO.StreamReader that doesn't have any way of reading from it and I can't find any documentation on it (Google and Bing give 0 results). It gets strange. It stays a System.IO.StreamReader if I don't try to read from it in the block.

I'm still relatively new to PowerShell and not sure if this is expected behavior.

  • PowerShell: 5.1.14393.5127
  • .NET: 4.7.3946.0

Given

function runProg(
    [parameter(Mandatory)][string]$exe,
    [object[]]$params=@(),
    [switch]$redirectOutput,
    [switch]$redirectError,
    [switch]$redirectInput
){
    $args= ($params.ForEach({ if($_ -is [System.IO.FileSystemInfo]){ ('"{0}"' -f $_.FullName) } elseif(($_.ToString().Contains(' '))){ ('"{0}"' -f $_) }else{ $_ } }) -join ' ')
    Write-Host "$exe $args"
    
    if ($redirectOutput -or $redirectError -or $redirectInput){
        $pinfo= New-Object System.Diagnostics.ProcessStartInfo;
        $pinfo.UseShellExecute= $false; #needed to redirect outputs and inputs
        $pinfo.FileName= $exe
        $pinfo.CreateNoWindow= $true
        $pinfo.RedirectStandardInput= $redirectInput
        $pinfo.RedirectStandardOutput= $redirectOutput
        $pinfo.RedirectStandardError= $redirectError
        $pinfo.Arguments= $args
        $proc= [System.Diagnostics.Process]::Start($pinfo);
    }else{
        $proc= Start-Process -FilePath $exe -PassThru -NoNewWindow -ArgumentList $args
    }
    $handle = $proc.Handle # force proc.Handle to populate https://stackoverflow.com/a/23797762/1479211
    return $proc
}

$p= runProg -redirectOutput 'powershell.exe' @((Get-Item 'test-long-output.ps1'))

The below gets the expected System.IO.StreamReader

$streamReader= {
    param($stream)
    Write-Host "`$stream.GetType" $stream.GetType().FullName
    Write-Host "`$stream.ReadLine?" ($null -ne $stream.ReadLine)
}
$streamJob= Start-Job -ArgumentList @($p.StandardOutput) -ScriptBlock $streamReader

The below gets the Deserialized.System.IO.StreamReader and errors on the missing ReadLine method.

$streamReader= {
    param($stream)
    Write-Host "`$stream.GetType" $stream.GetType().FullName
    Write-Host "`$stream.ReadLine?" ($null -ne $stream.ReadLine)
    do{
        $line= $stream.ReadLine();
        Write-Output $line
    }while($line -ne $null)
}
$streamJob= Start-Job -ArgumentList @($p.StandardOutput) -ScriptBlock $streamReader
Knyri
  • 2,968
  • 1
  • 17
  • 24

0 Answers0