Reputation: 53
Background: Our company uses a very old piece of software that our database programmers perform weekly maintenance on. When they perform maintenance, they have to end the process on remote computers before maintenance, otherwise it can cause corruption. This script is being made to try and help with their maintenance by quickly identifying computers running the process and later giving them the ability to remotely kill it.
Code I'm having issues with:
function Query-Processes ([System.Collections.ArrayList]$Computerlist)
{
Foreach ($Computer in $Computerlist)
{
Invoke-Command -ComputerName $Computer -AsJob -ScriptBlock {Get-Process | Where-Object {($_.ProcessName -eq 'ntvdm') -or ($_.ProcessName -eq 'Runform')}}
}
$arrJob_Results = @()
While ((Get-Job).Count -gt 0)
{
Get-Job | Where-Object {$_.State -eq 'Failed'} | Remove-Job
Get-Job | Where-Object {($_.State -eq 'Completed')} | ForEach-Object {
If ($_.HasMoreData -eq $False) {Remove-Job -Id $_.Id | Out-Null}
ElseIf ($_.HasMoreData -eq $True) {$arrJob_Results += Receive-Job -Id $_.Id}
}
}
return $arrJob_Results
}
Side note:Yes, it is checking for NTVDM because we have a critical piece of software that uses 16-bit DOS, welcome to our nightmare
How the function is called in my main script
$arr_RAVM = Test-Computers $arr_RAVM
$RAVM_Process = @(Query-Processes -Computerlist $arr_RAVM.Live)
The Problem When the function returns to the main script, the $RAVM_Process variable has the results of the Get-Process jobs, but also apparently some Get-Job output that is still in the pipeline.
When debugging the script in ISE I put two breakpoints, one on the return $arrJob_Results line and another on a junk variable I set in the main script. In function variable value
Notes
In the main script, the $arr_RAVM = Test-Computers $arr_RAVM
portion takes an initial array of computer names I queried from AD, and then runs them through a Test-Computers function that I use. That function then returns an object with three arrays: $arr_RAVM.Dead (failed ping test), $arr_RAVM.WinRMFailed (failed WinRM test), $arr_RAVM.Live (pingable remotely manageable computers). So if there is confusion on those lines that is what I'm doing
I know that Powershell can be tricky with return values, and that the return $arrJob_Results
line is more of telling the function that it can stop as opposed to actually returning only that value. So it seems like the issue is that I'm not capturing all the output in the function to variables, but I cannot figure out what is doing so. My thought was the: While (Get-Job)
line was doing it, so I tried doing other ways of creating a loop to process the jobs unsuccessfully.
I've tried a couple variations of the While loop such as
Get-Job | Where-Object {$_.State -eq 'Failed'} | Remove-Job
Get-Job | Where-Object {($_.State -eq 'Completed') -and ($_.HasMoreData -eq $True)} | Receive-Job | Foreach-Object {$arrJob_Results += $_}
Get-Job | Where-Object {($_.State -eq 'Completed') -and ($_.HasMoreData -eq $False)} | Remove-Job
But still receive the same result. When I get to the in function break point if I do anything like a "Get-Job" it'll be null. I also originally had the While conditional simply as While (Get-Job)
but the .Count part here was just part of trying random stuff.
Any help is greatly appreciated. This is the first instance in a script where I actually need to process the results of a background job (Used it before mainly in a "See if it just failed out or not" fashion) so it seems like there is something about jobs that I'm not understanding from what I've read.
Disclaimer: I am not a programmer and more coming from the "Sys/Network Admin that steadily keeps hacking together more complicated scripts" side. I have no formal education with programming so there are probably things I'm doing that aren't a good practice, but my goal is to understand what I'm doing wrong so I can improve.
Upvotes: 0
Views: 98
Reputation: 175085
The PSJob
objects you're seeing in the output is likely from Invoke-Command
in the initial foreach
loop.
Suppress the output from Invoke-Command
like you do subsequently with Remove-Object
:
Invoke-Command -ComputerName $Computer -AsJob -ScriptBlock { ... } |Out-Null
Upvotes: 1