Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Register Windows Startup/Shutdown script
function Register-EventScript {
param (
[string] $eventToRegister, # Either Startup or Shutdown
[string] $pathToScript,
[string] $scriptParameters
$path = "$ENV:systemRoot\System32\GroupPolicy\Machine\Scripts\$eventToRegister"
if (-not (Test-Path $path)) {
# path HAS to be available for this to work
New-Item -path $path -itemType Directory
# Add script to Group Policy through the Registry
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\$eventToRegister\0\0",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\$eventToRegister\0\0" |
ForEach-Object {
if (-not (Test-Path $_)) {
New-Item -path $_ -force
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\$eventToRegister\0",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\$eventToRegister\0" |
ForEach-Object {
New-ItemProperty -path "$_" -name DisplayName -propertyType String -value "Local Group Policy" -force
New-ItemProperty -path "$_" -name FileSysPath -propertyType String -value "$ENV:systemRoot\System32\GroupPolicy\Machine" -force
New-ItemProperty -path "$_" -name GPO-ID -propertyType String -value "LocalGPO" -force
New-ItemProperty -path "$_" -name GPOName -propertyType String -value "Local Group Policy" -force
New-ItemProperty -path "$_" -name PSScriptOrder -propertyType DWord -value 2 -force
New-ItemProperty -path "$_" -name SOM-ID -propertyType String -value "Local" -force
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\$eventToRegister\0\0",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts\$eventToRegister\0\0" |
ForEach-Object {
New-ItemProperty -path "$_" -name Script -propertyType String -value $pathToScript -force
New-ItemProperty -path "$_" -name Parameters -propertyType String -value $scriptParameters -force
New-ItemProperty -path "$_" -name IsPowershell -propertyType DWord -value 1 -force
New-ItemProperty -path "$_" -name ExecTime -propertyType QWord -value 0 -force
# get crrentlocation so we can form the full path to the script to register
$currentLocation = $PSScriptRoot
# register the script twice
Register-EventScript -eventToRegister "Startup" -pathToScript "$currentLocation\ScriptToRun.ps1" -scriptParameters "OnStartup"
Register-EventScript -eventToRegister "Shutdown" -pathToScript "$currentLocation\ScriptToRun.ps1" -scriptParameters "OnShutdown"
param (
[string] $message
function Run-Script {
param (
[string] $message
# get the date in our format
$date = Get-Date
Get-date $date -f "yyyyMMdd HH:mm:ss"
# log the date/time and the message
"$($date.ToUniversalTime().ToString("yyyyMMdd HH:mm:ss")) - $message" >> "C:\Temp\Log.txt"
# call the script with the incoming parameter
Run-Script -message $message
Copy link

rajbos commented Jul 15, 2020


The Register script will register the ScriptToRun.ps1 for both Machine Startup and Shutdown.
The ScriptToRun will then log those events to a text file for easy testing.


Tested on a Windows 10 VM (1909)


You need to run the register script with an elevated session

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment