PowerShell scripts are a great way to automate daily tasks or generate weekly reports. But how do you make a scheduled task for your PowerShell scripts? We can do this with either the task scheduler to run a PowerShell script or create the task in PowerShell.
The advantage of scheduled tasks is that you can set and forget them. They will run in the background, and update your systems, or generate the reports that you otherwise will have to do manually.
In this article
In this article, we will look at how to run a PowerShell script with task scheduler and how to create a scheduled task in PowerShell.
Use Task Scheduler to Run a PowerShell Script
The first option that we are going to look at is using the task scheduler in Windows to run a PowerShell Script. The Windows Task Scheduler originates from Windows 95! and is a great way to schedule tasks in Windows.
To run PowerShell scripts with the task scheduler, we can’t simply select the PowerShell file that we want to schedule. What we are going to do is run the “program” PowerShell and use the arguments to select the file that we want to run.
2 minutes
- Open Task Scheduler
- Create a new basic task

- Schedule the task
The trigger determines when the task should be executed. Choose a trigger, for example, Weekly, and click Next to configure when exactly the tasks need to be executed.
- Set the Action
Here comes the important part, for the action, we are going to Start a Program

- Start a Program – PowerShell
The program that we want to run is PowerShell. Just enter PowerShell in the Program/Script field (see screenshot in step 6), you don’t need to find the exact path to the executable.
- Add Arguments
In the arguments field, we are going to add the argument
-Fileand path to the PowerShell script. It’s also a good idea to add the PowerShell switch-NoProfileand set the-ExecutionPolicyto ByPass.If your scripts require any parameters then you can add them after the path (for example the -Output parameter):
-NoProfile -ExecutionPolicy Bypass -File "C:\scripts\ADHealth.ps1" -Output "HTML"
- Start in
Always set the Start in location to the same path as where your script is located. This way any exports that your script generates will be stored in the same location as your script. Otherwise, the output will be saved in C:\Windows\System32
- Finish

- Advanced Settings
There are two settings that we need to change for our scheduled PowerShell task. We will need to make sure that the script runs even when we are not logged on, which you do on the General tab.

- Save the task
Click Ok and enter your password, so the task can run when you are not logged on. It is always a good idea to test your task, right-click on it, and choose Run to run the task now.
We can of course also use PowerShell to create and manage scheduled tasks. Creating a scheduled task in PowerShell requires a couple of steps. For each step, there is a different cmdlet that we are going to use.
| Cmdlet | Description |
|---|---|
| New-ScheduledTaskTrigger | Creates a trigger object for a scheduled task |
| New-ScheduledTaskAction | Creates the action for a scheduled task |
| Register-ScheduledTask | Registers a scheduled task |
| Get-ScheduledTask | Show the scheduled tasks |
$taskTrigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Friday -At 3am $taskAction = New-ScheduledTaskAction -Execute "PowerShell" -Argument "-NoProfile -ExecutionPolicy Bypass -File 'C:\scripts\ADHealth.ps1' -Output 'HTML'" -WorkingDirectory 'c:\scripts' Register-ScheduledTask 'Lazy PS Tasks' -Action $taskAction -Trigger $taskTrigger
This will create the exact same task that we have created with the task scheduler. But let’s explain each of the cmdlets to see what options we have.
Creating the Trigger – New-ScheduledTaskTrigger
The first step is to define the trigger. This determines when we want to run the task. Just like with the task scheduler, we can define multiple triggers for our task.
The New-ScheduledTaskTrigger cmdlet comes with a couple of parameters that allow you to define when you want to task to run:
- AtLogOn – Runs the task when a user logs on
- AtStartup – When the system is started
- At – Used with Once, Daily, or Weekly. Defines the specific time to run the task
- Daily – Runs every day. Define the days with DaysOfWeek
- DaysInterval – Run every x days
- DaysOfWeek – This can be used with Daily or Weekly. Defines which days to run the task
- Weekly – Runs the tasks every week
- WeeklyInterval – Determines the interval between the weeks.
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Tuesday,Thursday -At 8:30am
Defining the Action – New-ScheduledTaskAction
To create the scheduled task action in PowerShell we will need to define which program we want it to run, any arguments (the path to the PowerShell scripts for example), and optionally the working directory.
So to run our PowerShell script we will set the -Execute parameter to PowerShell and define the file path and other parameters in the -Argument parameter. If your scripts require it, you can set the –WorkingDirectory parameter to the path of your script
$action = New-ScheduledTaskAction -Execute 'PowerShell' -Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\scripts\ADHealth.ps1" -Output "HTML"'
Creating the Task – Register-ScheduledTask
With the trigger and action defined, we can create and register the scheduled task. We will need to give our task a name and I recommend adding a TaskPath (folder) as well. This will make it easier to retrieve your tasks later on.
Register-ScheduledTask -TaskName 'Lazy PS Tasks' -TaskPath 'LazyTasks' -Action $taskAction -Trigger $taskTrigger

As mentioned you can define multiple triggers and actions for your task. To do this you will need to add the trigger or actions in an array. For example, to run the task every Tuesday and Thursday and on the first day of the month we can do:
# Define the triggers for Tuesday and Thursday at 08:30 AM and when a user logs on $taskTriggers = @( New-ScheduledTaskTrigger -Weekly -DaysOfWeek Tuesday,Thursday -At 08:30, New-ScheduledTaskTrigger -AtLogon ) Register-ScheduledTask -TaskName 'Lazy PS Tasks' -TaskPath 'LazyTasks' -Action $taskAction -Trigger $taskTriggers
Running the Task with Different Privileges
Register-ScheduledTask -TaskName "Lazy PowerShell Tasks" -taskPath 'LazyTasks' -Action $taskAction -Trigger $taskTrigger -User "lazyadmin\Administrator" -Password 'yourPass123' -RunLevel Highest
View the Scheduled Task
You can view your created tasks in the task scheduler. But you can also retrieve the scheduled task with PowerShell. For this, we will need to use the cmdlet Get-ScheduledTask. If you run the cmdlet without any parameters, then it will retrieve all scheduled tasks on your computer.
And as you can see, that is quite a lot. That’s why it’s important to organize your tasks in folders by using the taskPath parameter. This way you can use the TaskPath parameter to view only our tasks:
Get-ScheduledTask -TaskPath \LazyTasks\
The task path always starts and ends with a backslash \. To view your tasks you will need to supply the TaskName. If the name is unique, then the name alone will be enough. Otherwise, you will need to supply the path as well:
Get-ScheduledTask -TaskName 'Lazy PS Tasks' -TaskPath \LazyTasks\ | Select *
As you can see in the screenshot above, we can’t see all the details of the task. To view the Actions or Triggers we will need to expand the properties. We can do this by using the ExpandProperty method or by saving the results in a variable:
Get-ScheduledTask -TaskName 'Lazy PS Tasks' -TaskPath \LazyTasks\ | Select -ExpandProperty Triggers # Or $task = Get-ScheduledTask -TaskName 'Lazy PS Tasks' -TaskPath \LazyTasks\ $task.Triggers
Updating Tasks
To update scheduled tasks with PowerShell you can use the Set-ScheduledTask cmdlet. It works similar to the Register-ScheduledTask cmdlet. Just create a new trigger or action first and then add it just like when you would create it.
# Define new trigger $newTrigger= New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 08:30 # Update the task Set-ScheduledTask -TaskName "Lazy PowerShell Tasks" -taskPath 'LazyTasks'-Trigger $newTrigger
Wrapping Up
Scheduling PowerShell Tasks can be done with both Task Scheduler and in PowerShell with the Register-ScheduledTask cmdlet. Personally, I find it easier to create the task using PowerShell, but to modify it, I find the task scheduler more convenient.
Nevertheless, you can use both options to schedule your PowerShell scripts. I hope you found this article helpful, if you have any questions, just drop a comment below.
Tracking scheduled tasks from Azure PowerShell
Launch your PowerShell window and execute the mkdir and cd commands to create a directory called powershell-task-monitor on your computer and change into it. This is where you’ll store the PowerShell scripts.
mkdir powershell-task-monitor
You’ll monitor the PowerShell scripts in four ways:
- Using manual scripts
- Using execution streams
- Using PowerShell transcripts
- Using third-party software
Monitoring using manual log entries
To manually track the script’s execution status, you write logs into a plain text file.
# This script and task.ps1 should be stored in the "powershell-task-monitor" directory.
$date = Get-Date
Write-Output "STARTING ON: $date" | Out-File -FilePath "./logfile.txt" -Append
# The task.ps1 script is assumed to be in the current directory (powershell-task-monitor)
$taskScriptPath = "./task.ps1"
In the code above, the success and failure events are represented by 0 and 1, respectively. These are randomly generated events for demonstration purposes.
- It fetches the current date and time stamps into a date variable using the Get-Date cmdlet. Then, it writes the variable value into the log file to record the task execution time.
- It executes a for loop 20 times (from 0 to 19), using the Get-Random cmdlet to generate a random number between 0 and 20 on each iteration. If the loop iterator equals the random number, the script considers the task failed and writes a 0 to the logFile.txt file. Otherwise, it writes 1.
Run the command below from your PowerShell terminal to execute the task.ps1 script. (If necessary, change the execution policy from restricted to remote signed.)
To achieve both successful and unsuccessful executions, run the command multiple times, as shown below:

Fig. 1: Running the task.ps1 script multiple times
Next, examine the content of logFile.txt to track your task execution.
As the image below confirms, there are two successful executions and three unsuccessful executions.

Fig. 2: Contents of the logfile.txt file
By analyzing the date, time, and numerical values, you can track the executions of the script to know when it passed or failed.
While this manual approach works for simple scripts, there are more scalable solutions for monitoring scripts executed within your cloud environment. For example, you can use Site24x7, a scalable cloud-based solution that provides features to monitor your website, cloud, and server solutions in real time.
Monitoring using execution streams
A PowerShell job allows you to automate script executions without human oversight or a designated schedule. After executing a job, you can use the Get-Job cmdlet to get the job object, which contains valuable details.
To start, create a job.ps1 file to store the script for job creation. Then, add the code below to it:
# Both job.ps1 and task.ps1 are stored in the "powershell-task-monitor" directory.$job = Get-Job -Name "Guess-ops" -IncludeChildJob
Similar to task.ps1, in the job.ps1, you’ve orchestrated a series of randomized successes and failures as a part of this demonstration.
The code above uses the Start-Job cmdlet to create a job named Guess-ops, which executes the task.ps1 script. The Out-Null cmdlet prevents the script from immediately logging the job result. Then, the Get-Job cmdlet retrieves the job by name and writes the object to the console.
Execute the job.ps1 script multiple times to see the script in action:
./job.ps1
./job.ps1
./job.ps1
./job.ps1
The image below shows that the job object contains a State property with a Boolean value to indicate whether the script passes or fails. Though task.ps1 repeatedly fails when running the job, it eventually passes, as highlighted below:

Fig. 3: Execution of the job.ps1 script
By using a PowerShell job, you benefit from the ability to automate your task execution and monitor its state in the job object.
This method is more efficient and informative than using log files manually. However, running the Get-Job cmdlet within a managed cloud environment might be impossible.
The next approach uses the PowerShell transcript to automatically record the execution of a script and analyze the data generated within the transcript.
Monitoring using PowerShell transcripts
A transcript provides a feature to automatically record all or part of your PowerShell session to a text file without manually writing the entries using an output cmdlet.
Execute the commands below to start a transcript session using the Start-Script cmdlet and run the task.ps1 script several times, then stop the transcript session using the Stop-Script cmdlet:
# This script is meant to be stored and run from the "powershell-task-monitor" directory.
Start-Transcript -Path ./transcript.txt -Append./task1.ps1
./task1.ps1
./task1.ps1
./task1.ps1
./task1.ps1
./task1.ps1
With the -Path parameter, the transcript records the activities into a transcript.txt file within the project. Additionally, the -Append parameter causes the cmdlet to add new transcripts into the same file without overwriting any existing content.

Fig. 4: Executing the task.ps1 script
Next, use the cat command to output the content of the transcript.txt file to the console:

Fig. 5: Content of the transcript.txt file
Knowing that a transcript records all activities within a session, you can expect the output file to contain both valuable and irrelevant information. With the select-string cmdlet, you can search for lines containing helpful information, such as the TerminatingError message, when looking for errors. To search for this message, execute the command below:
Select-String –Path .\transcript.txt -Pattern "TerminatingError"
The select-string cmdlet searches the transcript.txt file for all lines containing the TerminatingError text.

Fig. 6: Using the select-string cmdlet to search the transcript.txt file
Over the past three sections, you monitored your PowerShell scripts using do-it-yourself (DIY) solutions that surround log entries.
Now that you’ve tried multiple DIY solutions for monitoring your tasks, you’ll discover how to use Site24x7’s heartbeat monitoring tool to monitor your PowerShell tasks externally.
Monitoring using a third-party solution
The heartbeat monitor oversees the execution of scripts, agents, daemons, and workers. It visualizes the error reports from your PowerShell scripts in real time and displays them on the web dashboard.
This feature provides a URL endpoint that expects your script to ping at various intervals to indicate that it’s operating successfully.
To configure a heartbeat monitor for your task.ps1 script, direct your browser to your Site24x7 dashboard.
Then, click Server on the navigation bar and select Heartbeat Monitoring.

Fig. 7: Heartbeat Monitoring feature
Click Add a Heartbeat Monitor. On the page that opens, provide your monitor details and configure its behavior.
Enter your preferred values into the Display Name and Name used in Ping URL fields and leave the other fields as default.
This demonstration uses powershell-script-monitor for both the display name and ping URL.

Fig. 8: The display name and the ping URL are both powershell-script-monitor
Click Save to store the details for your new monitor.
The dashboard will redirect you to the Setup page, which provides code snippets to quickly integrate the monitor using the endpoint URL in a Ruby, PowerShell, Cron, Bash, or Python project.
Click the PowerShell tab to see how to make a GET request using the Invoke-WebRequest cmdlet to your monitor’s endpoint.

Fig. 9: Making a GET request from the PowerShell tab
Now, you’ll add the heartbeat monitor to the PowerShell project.
Modify your task.ps1 script with the code below to add the Invoke-WebRequest cmdlet. This cmdlet pings the heartbeat monitor when the script executes successfully and removes the code for making a log entry.
Note: Replace the HEARTBEAT_MONITOR_ENDPOINT_URL placeholder below with your unique heartbeat monitor URL:
# This code is part of task.ps1 and is part of “powershell-task-monitor” directory.
for (($i = 0); $i -lt 20; $i++) {
$a = Get-Random -Maximum 20Write-Host "TASK SUCCESSFUL!"
Invoke-WebRequest 'HEARTBEAT_MONITOR_ENDPOINT_URL'
Next, execute the task.ps1 script multiple times until it both fails and succeeds.

Fig. 10: Executing the task.ps1 script repeatedly
Your heartbeat monitor dashboard provides concise details about when and at what intervals the ping registered.

Fig. 11: Heartbeat monitor dashboard showing ping details
Conclusion
You’ve now explored numerous strategies for monitoring the execution of your scheduled PowerShell tasks and experienced the benefits and drawbacks of each approach.
While you can manage simple tasks using DIY solutions, 24×7’s heartbeat monitor excels at handling complex systems. It tracks and monitors the availability of your PowerShell scripts, offering several essential features. These include automatically aggregating your tasks’ monitored data and creating detailed visual reports that highlight the most valuable insights.
The heartbeat monitor is one of many advanced monitoring tools that Site24x7 offers. You can explore more about both basic and advanced monitoring solutions or request a demo for an engaging, hands-on experience.

- Overview of PowerShell
- Key features and capabilities
- Installing and configuring PowerShell
- PowerShell syntax, cmdlets, and pipelines
- Working with objects in PowerShell
- Scripting with PowerShell
- Automating tasks and workflows
- Managing Windows systems and services
- Best practices for writing PowerShell scripts
An Introduction to PowerShell
PowerShell is Microsoft’s standardized command-line shell and scripting language for managing Windows operating systems and applications. It has been a built-in component of Windows since Windows 7 and Windows Server 2008 R2.
Key features of PowerShell include:
- Provides a powerful command-line shell for managing systems
- Implements a scripting language for automating tasks
- Allows access to the .NET Framework from the command line
- Exposes Windows management instrumentation via easy-to-use cmdlets
- Offers robust scripting capabilities for batch processing commands
- Provides a hosting API for integrating PowerShell into apps
- Designed for system automation and task scheduling
Compared to other scripting languages, PowerShell aims to provide a simple, consistent syntax and experience built on top of the .NET Framework. It leverages .NET classes to expose Windows APIs in an easy manner.
Now that we’ve covered the basics, let’s walk through installing and configuring PowerShell on Windows.
Installing and Configuring PowerShell
PowerShell comes built-in with Windows 7, Windows Server 2008 R2 and later versions. To verify if you have PowerShell installed, open the Command Prompt and type powershell.
If PowerShell is installed, you will enter the PowerShell interactive shell. Type exit to quit the shell.
For older Windows versions, you can install PowerShell via the Windows Management Framework downloads from Microsoft. This allows you to get the latest PowerShell updates on legacy operating systems.
Once PowerShell is installed, you can customize your environment via the PowerShell profile script. This allows you to set aliases, functions, variables, and other preferences that load each time you start the shell.
To configure your profile, create a PowerShell script called Microsoft.PowerShell_profile.ps1 saved to either of these folders:
$HOME\Documents\WindowsPowerShell\for your personal profile$PSHOME\Microsoft.PowerShell_profile.ps1as the global profile for all users
function prompt { Write-Host "$(Get-Date -Format G) [Administrator]" -ForegroundColor Cyan Write-Host " $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) " # Prompt for input return " "
}Profiles allow you to customize aliases, functions, environment variables, and PowerShell preferences. Now let’s dive into the PowerShell syntax.
Understanding PowerShell Syntax
For example, to retrieve a list of running processes:
PS C:\> Get-ProcessThis cmdlet verb Get acts on the processes noun to return all active processes on the system.
Cmdlets can take positional parameters which alter their behavior or pass input objects. Parameters are indicated with a dash -Name or can be positioned directly like Get-Process PowerShell.
PS C:\> Get-Process | Where-Object { $_.CPU -gt1000 }This gets processes, filters those over 1000 CPU, and passes them down the pipeline.
Beyond cmdlets, PowerShell supports all the usual programming syntax like variables, loops, conditionals, switches, functions, classes, etc. Let’s look at a few examples:
$processName = "PowerShell"
Get-Process -Name $processName$cpu = Get-Process PowerShell | Select-Object-ExpandProperty CPU
if ($cpu-gt1000) { Write-Host"CPU is high!"
} else { Write-Host"CPU is normal"
}$processes = Get-Processfor($i = 0; $i-lt$processes.length; $i++) { Write-Host$processes[$i]
}function Get-TopProcesses { Get-Process | Sort-Object-Property CPU -Descending | Select-Object-First10
}
Get-TopProcessesNow that we’ve covered the basics of using PowerShell interactively, let’s look at how we take these concepts to the next level with scripting.
Scripting with PowerShell
A key strength of PowerShell is its scripting capabilities for automation and batch processing. PowerShell scripts contain commands in a PowerShell document saved with a .ps1 extension.
Scripts offer benefits like:
- Automating repetitive tasks
- Encouraging re-use for consistency
- Allowing non-interactive execution
- Centralizing procedures and policies
- Enabling version control and sharing
Let’s walk through a simple PowerShell script example that prints a message and executes a set of commands:
# Sample PowerShell Script
Write-Host "Running PowerShell script!"
Get-Service -Name 'Bits'
Start-Service -Name 'Bits'
Write-Host "Started Bits service."
Get-Process -Name 'Outlook'
Stop-Process -Name 'Outlook'This prints a message, gets the status of the Bits service, starts it, and then kills any Outlook processes running.
To execute the script, run:
PS C:\> .\myScript.ps1Where myScript.ps1 is the name of our example script.
Scripts can utilize all the programming syntax we’ve discussed like variables, conditionals, loops, functions, classes, etc. They support passing arguments for parameterized scripts.
param( [string]$ServiceName
)
Get-Service -Name $ServiceName
if ((Get-Service -Name $ServiceName).Status -ne 'Running') { Start-Service -Name $ServiceName Write-Host "Started $ServiceName service"
}This defines a $ServiceName parameter that is passed when invoking the script. The script looks up the service status and conditionally starts it if it is not already running.
To execute a parameterized script:
PS C:\> .\Start-Service.ps1 -ServiceName 'Bits' This passes ‘Bits’ to the $ServiceName parameter.
Now let’s shift gears to look at how we can utilize PowerShell to automate workflows and processes in Windows.
A major advantage of PowerShell is its ability to automate workflows for performing repetitive tasks. Some examples include:
- Bulk user account creation
- Automated server provisioning
- Batch software deployment
- Nightly backup processes
- Task scheduling
PowerShell makes it easy to script these procedures and trigger them on demand or on a schedule.
For instance, to automate a nightly file backup:
# Backup-Files.ps1
$backupDir = "D:\Backups"
$folders = Get-ChildItem -Path "C:\Users"
foreach ($folder in $folders) { $fromPath = $folder.FullName $toPath = Join-Path -Path $backupDir -ChildPath $folder.Name Copy-Item -Path $fromPath -Destination $toPath -Recurse -Force Write-Host "Backed up $fromPath to $toPath"
}We could then schedule this to run nightly with Task Scheduler using a trigger like:
Trigger: Daily
At: 11pm
Repeat: IndefinitelyFor software deployment, PowerShell provides cmdlets like Install-Package to deploy MSI packages:
$packages = @('package1.msi', 'package2.msi')
foreach ($package in $packages) { Write-Host "Installing package: $package" Start-Process msiexec.exe -ArgumentList "/i $package /quiet" -Wait
}This iterates through an array of packages, prints a message, and installs them quietly via msiexec.exe.
Managing Windows with PowerShell
Some examples include:
Get-Service– Get service statusStart-Service– Start a serviceStop-Service– Stop a running serviceRestart-Service– Restart a serviceNew-Service– Create a new service
Get-Process– List running processesStop-Process– Stop a processStart-Process– Start a new processWait-Process– Wait for a process to finish
Get-EventLog– Get Windows event logsClear-EventLog– Clear an event logWrite-EventLog– Write an event to a log
Get-WindowsUpdate– View available updatesInstall-WindowsUpdate– Install updates
Get-NetIPConfiguration– View IP address settingsSet-DNSClientServerAddress– Set DNS serversTest-NetConnection– Test network connectivity
Get-ADUser– Query AD usersNew-ADUser– Create a new AD userSet-ADUser– Modify an AD userRemove-ADUser– Delete an AD user
Get-ChildItem– List files and foldersCopy-Item– Copy files and foldersMove-Item– Move files and foldersRemove-Item– Delete files and folders
Let’s walk through a few usage examples of managing services with PowerShell:
Get status of the Print Spooler service:
PS C:\> Get-Service -Name 'Spooler'Restart a stopped service:
PS C:\> Restart-Service -Name 'Spooler'Disable a service:
PS C:\> Set-Service -Name 'BITS' -StartupType DisabledCreate a new file system watcher service:
PS C:\> New-Service -Name 'FileWatcher' -BinaryPathName 'C:\FileWatcher.exe'These examples demonstrate how PowerShell enables you to directly control Windows components like services, processes, updates, networking, logs, AD, file system, and more.
Best Practices for PowerShell Scripting
- Add comment-based help for documenting scripts
- Leverage parameterized scripts with input validation
- Use consistent verb-noun naming for custom functions
- Avoid hardcoded values, use variables instead
- Handle errors gracefully with try/catch blocks
- Allow scripts to be run non-interactively with -NoProfile
- Format output for readability with spaces, newlines, and text
- Always test scripts thoroughly before production use
- Use version control like Git for change tracking
- Store scripts in a source-controlled repository
- Limit rights exposure – avoid using Admin accounts in scripts
- Don’t expose passwords or secrets in scripts
- Call scripts from wrapper scripts for consistency
Adopting standards and best practices for PowerShell scripts will serve you well over time and allow others to understand and leverage your code.
Conclusion
- Overview of PowerShell and its capabilities
- Installing and configuring PowerShell
- PowerShell syntax, cmdlets, and pipelines
- Scripting with PowerShell for automation
- Managing Windows services, processes, and components
- Best practices for writing PowerShell scripts
With PowerShell’s robust command-line interface, .NET integration, and universal scripting language, you can control nearly every aspect of Windows systems and solve real-world problems.

