Note: I am trying to run
packer.exeas a background process to workaround a particular issue with theazure-armbuilder, and I need to watch the output. I am not usingStart-Processbecause I don't want to use an intermediary file to consume the output.
I have the following code setting up packer.exe to run in the background so I can consume its output and act upon a certain log message. This is part of a larger script but this is the bit in question that is not behaving correctly:
$builderDir = ( Split-Path -Parent $PSCommandPath )
Push-Location $builderDir
# Set up the packer command to run asynchronously
$pStartProps = @{
FileName = ( Get-Command -CommandType Application packer ).Source
Arguments = "build -var-file ""${builderDir}\win-dev.pkrvars.hcl"" -only ""azure-arm.base"" ."
UseShellExecute = $false
RedirectStandardOutput = $true
RedirectStandardError = $false
LoadUserProfile = $true
}
$pStartInfo = New-Object ProcessStartInfo -Property $pStartProps
$p = [Process]::Start($pStartInfo)
while ( $null -ne ( $output = $p.StandardOutput.Readline() ) -or !$p.HasExited ) {
# Do stuff
}
Basically, the ( $output = $p.StandardOutput.Readline() ) portion of the while condition seems to be hanging until there is more output to be read. I'm not sure why this is, because StreamReader.Readline() should either return the next line to be read, or null if there is no more output. I have a fair bit of processing around this regarding the log message I'm expecting to get, so blocking when reading STDOUT when there is no further output to consume renders the script useless. There are other things it is doing in the foreground while packer.exe continues to execute.
I am able to confirm in the debugger that Readline() does read empty lines (value of "") fine, this seems to happen be when there is not yet further output to consume. This may be tangential but this causes the debugger to bug out as well.
When this issue occurs the VSCode debugger sits on this with$output = $p.StandardOutput.Readline() highlighted for a few seconds, then the debugger stops (everything disappears, no more variable tracking, etc.) until Readline() stops blocking and execution continues, at which point the debugger seems to re-initialize the tracked variables, watched expressions, etc. So I can't use the debugger at all when this occurs. Even thePowerShell Integrated Console (the one used with the debugger) hangs and I cannot type anything.
For full context, the goal of this script is to let packer.exe do its thing while I loop continuously to:
- Display more output from
packer.exe - Check for the presence of a certain log message
- Give
packer.exea bit of time to try to do what it needs on its own - If it waits too long, I execute a script against the node being since what
packer.exeshould have done on its own likely failed- I am using
Invoke-AzVMRunCommandto do this, which can't be done at the statepacker.exefor the issue I am working around. It must be performed out-of-band of thepacker.exerun itself.
- I am using
- The build continues on after the workaround is applied and I simply continue forwarding the output of
packer.exeto the console until the process exits
But since the script hangs when there is no output, step 4 will never work as I have to give packer time to try to complete the config on its own, and is the entire reason why I'm hacking this together in the first place.
Why is Readline() blocking here? Am I doing something incorrectly? This behavior occurs whether I run my script in Windows PowerShell or PowerShell Core.