Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Using Start-Job as a Scheduled Task

Posted on January 5, 2012

Here's a technique you might want to use for ad hoc troubleshooting or reporting. Even though it is possible to set up scheduled tasks to run PowerShell commands or scripts, it is cumbersome and time consuming. PowerShell v3 offers a great alternative, but I'll cover that another day. Suppose I want to do something every 15 minutes such as check the status of a service. Instead of going through the effort of creating a scheduled task, I'll create a PowerShell job.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

If I setup a job, it will run in my PowerShell session for as long as it needs to run or until I close my PowerShell session. Thus the trick is to keep the job running which easy to accomplish with a simple While loop.


While ($True) {
#do something
}

This will loop indefinitely because True is always True. In an interactive session, I can break out of this using Ctrl+C or insert code to break out if some condition is met. If I use this loop in my Start-Job command, the command will run indefinitely until the job terminates. I can always kill the job with the Stop-Job cmdlet. Although I suppose you should be careful with the code you put in the While loop as part of job because if you use Stop-Job, there's no way of knowing what code might be executing at the time. But for my use of this technique I'm keeping it simple and quick.

The other part is the timing interval. This is easily accomplished using the Start-Sleep cmdlet and specifying a value in milliseconds, or more typically, seconds. Depending on your task you could also take advantage of eventing, but that too is a bit complicated to setup and tear down. So, now the main part of my While loop looks like this:


While ($True) {
#do something
Start-Sleep -seconds 900
}

My code will run every 900 seconds (15 minutes). Here's a longer example that I put in a script.


$file="c:\work\mylog.txt"
#the number of seconds to pause between checks
$seconds=600
#the service to check
$service="Spooler"
#the computer to check
$computer=$env:computername

while ($True) {
$s=get-service $service -ComputerName $computer
$t="{0} Service {1} on {3} has a status of {2}" -f (Get-Date), $s.name,$s.status,$computer
$t | Out-File -FilePath $file -Append
Start-Sleep -seconds $seconds
}

I could have put all of that into a script block and created the job, or I could use the script.


PS C:\> start-job -FilePath C:\scripts\PollService.ps1

The job will write the service status information to a local text file every 10 minutes. When I'm done I can simply my PowerShell session or run Stop-Job. Here's where it can really get interesting: how about running this "scheduled task" ON a remote computer? There are two approaches. It depends on where you want the job to live. I could keep the job on my computer:


PS C:\> invoke-command -FilePath C:\scripts\PollService.ps1 -ComputerName quark -asjob
PS C:\> get-job 3 | format-list

HasMoreData : True
StatusMessage :
Location : quark
Command : #requires -version 2.0

$file="c:\work\mylog.txt"
#the number of seconds to pause between checks
$seconds=600
#the service to check
$service="Spooler"
$computer=$env:computername

while ($True) {
$s=get-service $service -ComputerName $computer
$t="{0} Service {1} on {3} has a status of {2}" -f (Get-Date),
$s.name,$s.status,$computer
$t | Out-File -FilePath $file -Append
Start-Sleep -seconds $seconds
}
JobStateInfo : Running
Finished : System.Threading.ManualResetEvent
InstanceId : 03a48cd0-f21a-4b7d-9a78-f148ec784ff8
Id : 3
Name : Job3
ChildJobs : {Job4}
Output : {}
Error : {}
Progress : {}
Verbose : {}
Debug : {}
Warning : {}
State : Running

The job object is on my (local) computer, even though the task is running on the remote computer. The other approach is to put the job ON the remote computer. This is a little trickier since I have to get the code I want to run ON the remote computer. I could copy the script over. Or I might try something like this:

First I want to convert my script into a scriptblock by stripping out the comments and inserting a semi colon at the end of each line. Then I can create a scriptblock from this text on the remote computer.


PS C:\> $text=get-content C:\scripts\PollService.ps1 | where {$_ -notmatch "^#" -AND $_} | foreach {"$_;"}

I can pass this text as a parameter with invoke-command to setup a job on the remote computer. I recommend using a PSSession in case you want to go back later and stop the job.


PS C:\> $quark=new-pssession -comp quark
PS C:\> invoke-command -scriptblock {param ($txt) $sb=$executioncontext.invokecommand.newscriptblock($txt) ; Start-job -scriptblock $sb } -session $quark -ArgumentList ($text | out-string)

The job is created on the remote session and runs indefinitely.


PS C:\> invoke-command {get-job -State Running} -Session $quark

WARNING: 2 columns do not fit into the display and were removed.

Id Name State HasMoreData Location
-- ---- ----- ----------- --------
17 Job17 Running True localhost
PS C:\> invoke-command {get-content C:\work\mylog.txt} -Session $quark
1/5/2012 9:37:41 AM Service Spooler on QUARK has a status of Running
1/5/2012 9:38:46 AM Service Spooler on QUARK has a status of Running
1/5/2012 10:44:54 AM Service Spooler on QUARK has a status of Running

As I mentioned there are probably several ways you could do this. When I am finished I can either terminate the PSSession or stop the remote job.


PS C:\> invoke-command {stop-job -State Running -PassThru} -Session $quark

WARNING: 2 columns do not fit into the display and were removed.

Id Name State HasMoreData Location
-- ---- ----- ----------- --------
17 Job17 Stopped False localhost

So the next time you need some scheduled PowerShell, at least on a temporary basis, take a look at Start-Job.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

1 thought on “Using Start-Job as a Scheduled Task”

  1. Pingback: Friday Fun: A PowerShell Alarm Clock | The Lonely Administrator

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d