ScheduledJobFunctions.ps1
Function Get-ScheduledJobDetail { [CmdletBinding(DefaultParameterSetName = "name")] [OutputType("ScheduledJobDetail")] Param( [Parameter(Position = 0, ValueFromPipeline, Mandatory, ParameterSetName = "name")] [ValidateNotNullorEmpty()] [string[]]$Name, [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = "job")] [ValidateNotNullorEmpty()] [alias("job")] [Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]$ScheduledJob ) Begin { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)" } #begin Process { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Using parameter set $($pscmdlet.ParameterSetName)" $jobs = @() if ($PSCmdlet.ParameterSetName -eq 'name') { foreach ($item in $name) { Try { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting scheduledjob $item" $jobs += Get-ScheduledJob -Name $item -ErrorAction Stop } Catch { Write-Warning $_.exception.message } } } #if Name else { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Using scheduledjob $($scheduledjob.name)" $jobs += $ScheduledJob } Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting scheduledjob details" foreach ($job in $jobs) { #get corresponding task Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] $($job.name)" $task = Get-ScheduledTask -TaskName $job.name $info = $task | Get-ScheduledTaskInfo [pscustomobject]@{ PSTypeName = "ScheduledJobDetail" ID = $job.ID Name = $job.name Command = $job.command Enabled = $job.enabled State = $task.State NextRun = $info.nextRunTime MaxHistory = $job.ExecutionHistoryLength RunAs = $task.Principal.UserID Frequency = $job.JobTriggers.Frequency Days = $job.JobTriggers.DaysOfWeek RepetitionDuration = $job.JobTriggers.RepetitionDuration RepetitionInterval = $job.JobTriggers.RepetitionInterval DoNotAllowDemandStart = $job.options.DoNotAllowDemandStart IdleDuration = $job.options.IdleDuration IdleTimeout = $job.options.IdleTimeout MultipleInstancePolicy = $job.options.MultipleInstancePolicy RestartOnIdleResume = $job.options.RestartOnIdleResume RunElevated = $job.options.RunElevated RunWithoutNetwork = $job.options.RunWithoutNetwork ShowInTaskScheduler = $job.options.ShowInTaskScheduler StartIfNotIdle = $job.options.StartIfNotIdle StartIfOnBatteries = $job.options.StartIfOnBatteries StopIfGoingOffIdle = $job.options.StopIfGoingOffIdle StopIfGoingOnBatteries = $job.options.StopIfGoingOnBatteries WakeToRun = $job.options.WakeToRun } } #foreach job } #process End { Write-Verbose "[$((Get-Date).TimeofDay) END] Ending $($myinvocation.MyCommand)" } #end } Function Remove-OldJobResult { [cmdletbinding(SupportsShouldProcess, DefaultParameterSetName = "name")] [OutputType("None")] Param( [Parameter(Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = "name")] [ValidateNotNullorEmpty()] [string[]]$Name, [Parameter(Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = "job")] [ValidateNotNullorEmpty()] [alias("job")] [Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]$ScheduledJob ) Begin { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)" } #begin Process { #get all but newest job result for cleanup if ($PSCmdlet.ParameterSetName -eq 'name') { $items = $Name } else { $items = $ScheduledJob.Name } Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Removing old job results for $($items -join ',')" Get-Job -name $items | Sort-Object PSEndTime -descending | Select-Object -skip 1 | Remove-Job } #process End { Write-Verbose "[$((Get-Date).TimeofDay) END] Ending $($myinvocation.MyCommand)" } #end } Function Export-ScheduledJob { [cmdletbinding(SupportsShouldProcess, DefaultParameterSetName = "name")] [OutputType("None", "System.IO.FileInfo")] [Alias("esj")] Param( [Parameter(Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = "name")] [ValidateNotNullorEmpty()] [string]$Name, [Parameter(Position = 0, Mandatory, ValueFromPipeline, ParameterSetName = "job")] [ValidateNotNullorEmpty()] [alias("job")] [Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]$ScheduledJob, [ValidateScript( { if (-Not (Test-Path -path $_)) { Throw "Could not verify the path." } else { $True } })] [ValidateScript( { Test-Path $_ })] [string]$Path = (Get-Location).Path, [switch]$Passthru ) Begin { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)" } #begin Process { if ($Name) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting scheduled job $job" Try { $ExportJob = Get-ScheduledJob -Name $name -ErrorAction Stop } Catch { Write-Warning "Failed to get scheduled job $name" #bail out Return } } #if else { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Using scheduled job $($scheduledjob.name)" $ExportJob = $scheduledjob } $ExportPath = Join-Path -Path $path -ChildPath "$($ExportJob.Name).xml" Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Starting the export process of $($ExportJob.Name) to $ExportPath" $ExportJob | Select-Object -property Name, @{Name = "Scriptblock"; Expression = { ($_.InvocationInfo.Parameters.Item(0) | Where-Object { $_.name -eq "ScriptBlock" }).value } }, @{Name = "FilePath"; Expression = { ($_.InvocationInfo.Parameters.Item(0) | Where-Object { $_.name -eq "FilePath" }).value } }, @{Name = "ArgumentList"; Expression = { ($_.InvocationInfo.Parameters.Item(0) | Where-Object { $_.name -eq "ArgumentList" }).value } }, @{Name = "Authentication"; Expression = { ($_.InvocationInfo.Parameters.Item(0) | Where-Object { $_.name -eq "Authentication" }).value } }, @{Name = "InitializationScript"; Expression = { ($_.InvocationInfo.Parameters.Item(0) | Where-Object { $_.name -eq "InitializationScript" }).value } }, @{Name = "RunAs32"; Expression = { ($_.InvocationInfo.Parameters.Item(0) | Where-Object { $_.name -eq "RunAs32" }).value } }, @{Name = "Credential"; Expression = { $_.Credential.UserName } }, @{Name = "Options"; Expression = { #don't export the job definition here $_.Options | Select-Object -property * -ExcludeProperty JobDefinition } }, @{Name = "JobTriggers"; Expression = { #don't export the job definition here $_.JobTriggers | Select-Object -property * -ExcludeProperty JobDefinition } }, ExecutionHistoryLength, Enabled | Export-Clixml -Path $ExportPath if ($Passthru) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Writing the export file item to the pipeline" Get-Item -Path $ExportPath } Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Export finished." } #process End { Write-Verbose "[$((Get-Date).TimeofDay) END] Ending $($myinvocation.MyCommand)" } #end } #end Export-ScheduledJob Function Import-ScheduledJob { [cmdletbinding(SupportsShouldProcess)] [OutputType("None", "Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition")] [Alias("isj")] Param( [Parameter(Position = 0, Mandatory, ValueFromPipeline)] [alias("name", "pspath")] [ValidateScript( { if (-Not (Test-Path -path $_)) { Throw "Could not verify the path." } else { $True } })] [string]$Path, [switch]$Passthru ) Begin { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)" } #begin Process { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] processing $path" #define a hashtable of values for Register-ScheduledJob $paramHash = @{ ErrorAction = "Stop" } $Imported = Import-Clixml -path $Path #$cmd = "Register-ScheduledJob -name ""$($Imported.Name)""" $paramHash.Add("Name", $Imported.Name) if ($Imported.scriptblock) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found a scriptblock" $paramHash.Add("ScriptBlock", [scriptblock]::Create($Imported.Scriptblock)) } elseif ($Imported.FilePath) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found a filepath" #$cmd+= " -FilePath $($Imported.FilePath)" $paramHash.Add("FilePath", $Imported.Filepath) } else { #this should never really happen Write-Warning "Failed to find a scriptblock or file path" #bail out Return } Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing additional job elements" if ($Imported.ArgumentList) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..ArgumentList" $paramHash.Add("ArgumentList", $ImportFile.ArgumentList) } if ($Imported.Authentication) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..Authentication" $paramhash.Add("Authentication", $Imported.Authentication) } if ($Imported.Credential) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..Credential" $paramHash.Add("credential", $Imported.Credential) } if ($Imported.InitializationScript) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..InitializationScript" $paramHash.Add("InitializationScript", [scriptblock]::Create($Imported.InitializationScript)) } if ($Imported.ExecutionHistoryLength) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..ExecutionHistoryLength" $paramHash.Add("MaxResultCount", $Imported.ExecutionHistoryLength) } if ($Imported.RunAs32) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] ..RunAs32" $paramHash.Add("RunAs32", $True) } if ($Imported.Options) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing Options" $optionHash = @{ RunElevated = $Imported.Options.RunElevated HideInTaskScheduler = -Not ($Imported.Options.ShowInTaskScheduler) RestartOnIdleResume = $Imported.Options.RestartOnIdleResume MultipleInstancePolicy = $Imported.Options.MultipleInstancePolicy DoNotAllowDemandStart = $Imported.Options.DoNotAllowDemandStart RequireNetwork = -Not ($Imported.Options.RunWithoutNetwork) StopIfGoingOffIdle = $Imported.Options.StopIfGoingOffIdle WakeToRun = $Imported.Options.WakeToRun ContinueIfGoingOnBattery = -Not ($Imported.Options.StopIfGoingOnBatteries) StartIfOnBattery = $Imported.Options.StartIfOnBatteries IdleTimeout = $Imported.Options.IdleTimeout IdleDuration = $Imported.Options.IdleDuration StartIfIdle = -Not ($Imported.Options.StartIfNotIdle) } $jobOption = New-ScheduledJobOption @optionHash $paramhash.Add("ScheduledJobOption", $jobOption) } if ($Imported.JobTriggers) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing Job Triggers" #define an array to hold triggers $Triggers = @() #enumerate each job trigger foreach ($trigger in $Imported.JobTriggers) { #test for parameter set Switch ($trigger.Frequency.Value) { "Once" { $TriggerCmd = "New-JobTrigger -Once -At ""$($trigger.At)""" if ($trigger.RepetitionDuration) { $TriggerCmd += " -RepetitionDuration $($trigger.RepetitionDuration)" } if ($trigger.RepetitionInterval) { $TriggerCmd += "-RepetitionInterval $($trigger.RepetitionInterval)" } } #once "Weekly" { $TriggerCmd = "New-JobTrigger -Weekly -DaysOfWeek $($trigger.DaysOfWeek) -WeeksInterval $($trigger.Interval) -At ""$($trigger.At)""" } #weekly "Daily" { $TriggerCmd = "New-JobTrigger -Daily -DaysInterval $($trigger.Interval) -At ""$($trigger.At)""" } #Daily "AtLogon" { $TriggerCmd = "New-JobTrigger -AtLogOn -User $($trigger.user)" } #AtLogon "AtStartup" { $TriggerCmd = "New-JobTrigger -AtStartup" } #AtStartup Default { #no frequency Write-Warning "No trigger found" } #Default } #end switch #define a new trigger and add to the array $TriggerCmd += " -randomdelay $($trigger.RandomDelay)" Write-Verbose $triggerCmd $Triggers += Invoke-Expression -Command $TriggerCmd } #foreach trigger $paramHash.Add("Trigger", $Triggers) } Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating the scheduled job" Write-Verbose ($paramhash | Out-String) #create the scheduled job if ($PSCmdlet.ShouldProcess($imported.Name)) { $newJob = Register-ScheduledJob @paramhash #if the job is disabled, then if (-Not ($Imported.Enabled)) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Disabling the job" $newJob | Disable-ScheduledJob } if ($Passthru) { Get-ScheduledJob $imported.Name } } #should process } #process End { Write-Verbose "[$((Get-Date).TimeofDay) END] Ending $($myinvocation.MyCommand)" } #end } #close Import-ScheduledJob Function Get-ScheduledJobResult { [cmdletbinding()] [OutputType("ScheduledJobResult")] [Alias("ljr")] Param( [Parameter(Position = 0)] [ValidateNotNullorEmpty()] [string]$Name = "*", [validatescript( { $_ -gt 0 })] [int]$Newest = 1, [switch]$All ) Begin { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)" } #begin Process { #only show results for Enabled jobs Try { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting scheduled jobs for $name" $jobs = Get-ScheduledJob -Name $name -ErrorAction Stop #-ErrorVariable ev } Catch { Write-Warning "$Name : $($_.exception.message)" # $ev.errorRecord.Exception } if ($jobs) { #filter unless asking for all jobs if ($All) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting all jobs" } else { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting enabled jobs only" $jobs = $jobs | Where-Object Enabled } Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing $($jobs.count) found jobs" Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting newest $newest job results" $data = $jobs | ForEach-Object { #get job and select all properties to create a custom object Try { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Trying to get jobs for $($_.name)" Get-Job -Name $_.name -Newest $Newest -ErrorAction stop | ForEach-Object { [scheduledjobresult]::new($_) } } #Try Catch { Write-Warning $_.exception.message Write-Warning "Scheduled job $($_.TargetObject) has not been run yet." } } #Foreach Scheduled Job #write a sorted result to the pipeline Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Here are your $($data.count) results" $data | Sort-Object -Property PSEndTime -Descending } #if $jobs } #process End { Write-Verbose "[$((Get-Date).TimeofDay) END] Ending $($myinvocation.MyCommand)" } #end } #end function |