1

The following powershell script monitors a list of servers after they are rebooted and notifies immediately once it can attach with Get-Service.

#start all jobs here
get-job | stop-job
get-job | remove-job

$servers =  ("localhost", "127.0.0.1", "badserver")

function Ping-Service($myservers,[int]$timeout=60, [int]$waitbetweentrys=1){
    $myservers| %{
    $computername = $_
    start-job -scriptblock {
                   param(
               [string]$computername,
               [int]$maxwait,
               [int]$waitbetween
               )
               $status = "Fail"
               $StartTime = Get-Date
               $duration = 0
                do
               {
                #if successful, break out
                try {$gs = Get-Service -ComputerName $computername -ErrorAction Stop;$status = "Success";break} catch {start-sleep $waitbetween}                               
                $duration = (New-TimeSpan $StartTime $(Get-Date)).Seconds
                } while ($duration -lt $maxwait)
               $hash = [ordered]@{"Computername" = $computername; "Type" = "Service";"Status"=$status;"Done"=$(Get-Date);"Duration"=$duration}      
               $hash
           } -ArgumentList ($computername, $timeout, $waitbetweentrys)
}
}
Ping-Service -myservers $servers -timeout 10

#loops through jobs and check for completed ones
do
   {
       #process jobs that are done
       $jobsdone = Get-Job | where State -eq 'Completed'
       $joboutput = $jobsdone | Receive-Job

       $joboutput | %{New-Object PSObject -Property $_ } |ft -AutoSize

       #remove jobs once we get the output
       $jobsdone | Remove-job

       #See if there are any jobs left     
       $jobsleft = Get-Job

       #wait 5 seconds before checking jobs
       if ($jobsleft -ne $null) {start-sleep 5}

   } while ($jobsleft -ne $null)    #continue loop while there are jobs left

It works well, but the output is not formated how I would like it:

Duration Status  Computername Done                Type   
-------- ------  ------------ ----                ----   
       0 Success localhost    5/7/2013 4:09:30 PM Service



Duration Status  Computername Done                Type   
-------- ------  ------------ ----                ----   
       0 Success 127.0.0.1    5/7/2013 4:09:31 PM Service



Duration Status Computername Done                Type   
-------- ------ ------------ ----                ----   
      10 Fail   badserver    5/7/2013 4:09:42 PM Service

I would like it to look like this:

Duration Status  Computername Done                Type   
-------- ------  ------------ ----                ----   
       0 Success localhost    5/7/2013 4:09:30 PM Service
       0 Success 127.0.0.1    5/7/2013 4:09:31 PM Service
      10 Fail   badserver    5/7/2013 4:09:42 PM Service

However, the key is to have each result displayed in real time. Ironically, the start-job output at the top of the script is exactly what I want.

1 Answer 1

1

If you call Format-Table on each object in a loop, it will display them seperately. Output the orginial objects and PowerShell will do it's magic. Btw, why are you taking an object)job-output), and creating a new object that contains it? :S

Try replacing

$joboutput | %{New-Object PSObject -Property $_ } |ft -AutoSize

with

$joboutput

Or even simpler, drop $joboutput. Replace

$joboutput = $jobsdone | Receive-Job
$joboutput | %{New-Object PSObject -Property $_ } |ft -AutoSize

with

$jobsdone | Receive-Job
Sign up to request clarification or add additional context in comments.

3 Comments

I want to add all of the outputs together as an object so I can pass this value to another script. If I modify the output as you suggest, it will output a list view with two columns.
I'm not seeing the problem. Is the sample incomplete(is $jobsdone used somewhere else)? If so, use the first part of my answer to fix the visible output only. The only thing I removed was the unnecessary object-creation and format-table (which BY THE WAY, destroys the object you JUST created).
just to clarify more. if you save the code as a script and run it, it would return an ARRAY of the objects, that you can store and/or pass to another cmdlet/function/script. So if the default view is a list view, run something like myscript.ps1 | format-table -autosize. just remember not to use a format-... cmdlet in the code itself as it returns a special formatobject, and not the original dataobject itself.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.