I am trying to run a PowerShell script that runs CMD command and send the live stream back to PowerShell.
Each line that comes back from the stream, I am trying to send to a function; However, it is passed to the function only at the end of the cmd run instead of during it.
Important to mention that if I pass the stream to 'out-host' instead, I can see the results.
Can you assist?
function get-ValidateProgress
{
param ([Parameter(Mandatory,HelpMessage='Value Passed from ValidateLDS.exe',Position=0,ValueFromPipeline)]$ValidateLine)
IF($ValidateLine -like 'Proccessing Active Users record*' )
{
$Current=$ValidateLine -replace 'Proccessing Active Users record ','' -replace 'of.*','' -replace ' ',''
$TotalValue=$ValidateLine -replace "Proccessing Active Users record $Current of ",''
[INT]$Progress=(($Current/$TotalValue)*100)
Write-Progress -Id 1 -Activity ValidateDBLDS -Status 'Proccessing LDS User records' -PercentComplete $Progress -CurrentOperation 'Active Users'
IF($Current -eq $TotalValue){write-host 'Finished procccsing Active Users' -ForegroundColor Green}
}
ELSEIF($ValidateLine -like 'Proccessing Deleted Users record*' )
{
$Current=$ValidateLine -replace 'Proccessing Deleted Users record ','' -replace 'of.*','' -replace ' ',''
$TotalValue=$ValidateLine -replace "Proccessing Deleted Users record $Current of ",''
[INT]$Progress=(($Current/$TotalValue)*100)
Write-Progress -Id 1 -Activity ValidateDBLDS -Status 'Proccessing LDS User records' -PercentComplete $Progress -CurrentOperation 'Deleted Users'
IF($Current -eq $TotalValue){write-host 'Finished procccsing Deleted Users' -ForegroundColor Green}
}
}
Try{
$cmdOutput = cmd.exe /c "cd /d D:\$Campus\Code\Utilities && ValidateDBLDS.exe /viewonly:false" 2>&1 | get-ValidateProgress
Write-Host "Successfully finished LDS Validation." -ForegroundColor Green
sleep -Seconds 2
}
Catch{
Write-host "An Error occured during validating LDS. See full expection below.`nExecption:"$Error[0].Exception"`nTargetObject:"$Error[0].TargetObject"`nInvocationInfo:"$Error[0].InvocationInfo -ForegroundColor Red
}
CodePudding user response:
In order for your function to receive streaming input via the pipeline - i.e., output objects (which in the case of external programs are lines) as they're being emitted by the upstream command - it must use a process
block.
To use a simplified example:
function foo {
# A process block is executed for each pipeline input object.
# In the case of *external programs*, each *line* of output constitutes
# an input object.
process {
"[$_]"
}
}
cmd /c 'echo 1 & timeout 2 >NUL & echo 2 ' | foo
Executing this will echo [1 ]
before the 2-second sleep timeout.exe
call kicks in, proving that the cmd /c
output was processed in a streaming fashion.
A function that lacks a process
block is processed as if its body were enclosed in an end
block, i.e. the block that is invoked after all pipeline input has been received.