Yesterday I posted a quick update on my code to get the most recent scheduled job result in PowerShell. I had been using a simple script. But the more I thought about it, the more I realized I really did need to turn it into a function with more flexibility. When creating a PowerShell based tool you need to think about who might be using it. Even though I only wanted the last result for all enabled jobs, there might be situations where I wanted say the last 2 or 3. Any maybe I wanted to only get results for a specific job. Or maybe all jobs. The bottom line is that I needed more flexibility. Now I have the Get-ScheduledJobResult function.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
#requires -version 3.0 Function Get-ScheduledJobResult { <# .Synopsis Get scheduled job result. .Description This command will retrieve the last job result for a given scheduled job. By default, when you create a scheduled job, PowerShell will retain the last 32 job results. This command can help you get the most recent job result. The default behavior is to retrieve the newest job for all enabled scheduled jobs. But you can specify scheduled jobs by name, indicate if you want to see all jobs, and also the number of recent jobs. The command uses a custom type definition based on the Job object. .Parameter All Display all scheduled jobs. The default is enabled only. .Example PS C:\> Get-ScheduledJobResult Name : Download PowerShell v3 Help ID : 87 State : Completed Run : 00:01:40.9564095 Start : 9/16/2013 6:00:09 AM End : 9/16/2013 6:01:50 AM Name : Daily Work Backup ID : 55 State : Completed Run : 00:00:53.8172548 Start : 9/15/2013 11:55:05 PM End : 9/15/2013 11:55:59 PM .Example PS C:\> Get-ScheduledJobResult download* -Newest 5 | Select ID,State,Location,Start,End,Run,HasMoreData | Out-GridView -title "Download Help Job" Get the newest 5 job results for the Download* scheduled job, selecting a few properties and displaying the results in Out-Gridview. .Notes Last Updated: 9/16/2013 Version : 0.9 **************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** .Link https://jdhitsolutions.com/blog/2013/09/a-better-powershell-get-scheduled-job-results .Link Get-Job Get-ScheduledJob .Outputs Custom ScheduledJob Object #> [cmdletbinding()] Param( [Parameter(Position=0)] [ValidateNotNullorEmpty()] [string]$Name="*", [validatescript({$_ -gt 0})] [int]$Newest=1, [switch]$All ) #only show results for Enabled jobs Try { Write-Verbose "Getting scheduled jobs for $name" $jobs = Get-ScheduledJob -Name $name -ErrorAction Stop -ErrorVariable ev } Catch { Write-Warning $ev.errorRecord.Exception } if ($jobs) { #filter unless asking for all jobs Write-Verbose "Processing found jobs" if ($All) { Write-Verbose "Getting all jobs" } else { Write-Verbose "Getting enabled jobs only" $jobs = $jobs | where Enabled } Write-Verbose "Getting newest $newest job results" $data = $jobs | foreach { #get job and select all properties to create a custom object Get-Job $_.name -newest $Newest | Select * | foreach { #insert a new typename $_.psobject.typenames.Insert(0,'My.ScheduledJob.Result') #write job to the pipeline $_ } } #write result to the pipeline $data | Sort -Property PSEndTime -Descending } #if $jobs Write-Verbose "Finished" } #end function #define an alias Set-Alias -Name gsjr -Value Get-ScheduledJobResult
The function takes parameters that I can pass to Get-ScheduledJob and Get-Job. For the most part the core functionality remains the same: I get the X number of most recent jobs for scheduled jobs. The difference is that now these values are controlled by parameters. The other benefit to my revision is error handling. Before I had a single pipelined expression, but now I use a Try/Catch block to get the scheduled job by name, using * as the default. You'll also notice I'm using my own error variable. If there is an error, I can handle it more gracefully. I'll let you test it with a bogus scheduled job name to see what happens.
But perhaps the biggest change is that I define my own object type, based on the Job object.
$data = $jobs | foreach { #get job and select all properties to create a custom object Get-Job $_.name -newest $Newest | Select * | foreach { #insert a new typename $_.psobject.typenames.Insert(0,'My.ScheduledJob.Result') #write job to the pipeline $_ } }
For every job result insert a new typename. Because I might have multiple objects I need to insert the typename for each one. As I was working on this I originally was inserting my typename into the Microsoft.PowerShell.ScheduledJob.ScheduledJob object. But my custom formatting wasn't working property, so I found that by selecting all properties, which has the effect of creating a Selected.Microsoft.PowerShell.ScheduledJob.ScheduledJob my changes worked.
Inserting the typename is only part of the process. In the script file that defines the function, I included code to take advantage of Update-TypeData. In PowerShell 3.0 we no longer need to deal with XML files. Now type updates can be done on-the-fly. So instead of creating my custom properties with Select-Object and custom hash tables, I add them as alias properties. I so something similar to create the Run property.
#define default property set for my custom type $typename = 'My.ScheduledJob.Result' #define some alias properties $paramHash= @{ TypeName = $typename MemberType = "AliasProperty" MemberName = "Start" Value = "PSBeginTime" } Update-TypeData @paramHash -force $paramHash.MemberName="End" $paramHash.Value="PSEndTime" Update-TypeData @paramHash -Force #define a custom property $paramHash.MemberName="Run" $paramHash.Value={$this.PSEndTime - $this.PSBeginTime} $paramHash.memberType="ScriptProperty" Update-TypeData @paramHash -Force #set default display properties Update-TypeData -TypeName $typename -DefaultDisplayPropertySet Name,ID,State,Run,Start,End -Force
The last part of my revision is to define the default display property set. The effect is that when I run my function, if I don't specify any other formatting, by default I'll see the properties I want.
PS C:\> Get-ScheduledJobResult Name : Download PowerShell v3 Help ID : 89 State : Completed Run : 00:01:40.9564095 Start : 9/16/2013 6:00:09 AM End : 9/16/2013 6:01:50 AM Name : Daily Work Backup ID : 57 State : Completed Run : 00:00:53.8172548 Start : 9/15/2013 11:55:05 PM End : 9/15/2013 11:55:59 PM Name : Thunderbird Backup ID : 94 State : Completed Run : 00:51:08.2574182 Start : 9/10/2013 11:59:00 PM End : 9/11/2013 12:50:08 AM
And I still have access to all of the other properties as well.
PS C:\> Get-ScheduledJobResult download* -Newest 5 | Select ID,State,Location,Start,End,Run,HasMoreData,Command | Out-GridView -title "Download Help Job"
Now I have a tool, complete with an alias, with defaults that work for me, but if I need to see something else I can adjust the output based on my parameters. If you want to try this, save the function and type information to the same script file.
1 thought on “A Better PowerShell Get Scheduled Job Results”
Comments are closed.