Skip to content

Instantly share code, notes, and snippets.

@valen214
Created October 21, 2025 14:12
Show Gist options
  • Select an option

  • Save valen214/97ff856481bf6cfc1120d7440e1e4386 to your computer and use it in GitHub Desktop.

Select an option

Save valen214/97ff856481bf6cfc1120d7440e1e4386 to your computer and use it in GitHub Desktop.
restart windows explorer.exe from powershell with Windows Restart Manager API
# restart-explorer.ps1
# Restarts explorer.exe using Windows Restart Manager.
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
using System.Text;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct RM_UNIQUE_PROCESS
{
public int dwProcessId;
public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
}
// https://learn.microsoft.com/en-us/windows/win32/api/restartmanager/ns-restartmanager-rm_process_info
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct RM_PROCESS_INFO
{
public RM_UNIQUE_PROCESS Process;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string strAppName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string strServiceShortName;
public uint ApplicationType;
public uint AppStatus;
public uint TSSessionId;
[MarshalAs(UnmanagedType.Bool)]
public bool bRestartable;
}
// omitted RmGetFilterList RmAddFilter RmJoinSession RmCancelCurrentTask
public static class RestartManager
{
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
public static extern int RmStartSession(
out int pSessionHandle,
int dwSessionFlags,
StringBuilder strSessionKey
);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
public static extern int RmRegisterResources(
int dwSessionHandle,
uint nFiles,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] rgsFiles,
uint nApplications,
IntPtr rgApplications, // not used
uint nServices,
IntPtr rgsServiceNames // not used
);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
public static extern int RmGetList(
int dwSessionHandle,
out uint pnProcInfoNeeded,
ref uint pnProcInfo,
[In, Out] RM_PROCESS_INFO[] rgAffectedApps,
out uint lpdwRebootReasons
);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
public static extern int RmShutdown(
int dwSessionHandle,
uint lActionFlags,
IntPtr fnStatus // callback not used
);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
public static extern int RmRestart(
int dwSessionHandle,
uint lActionFlags,
IntPtr fnStatus // callback not used
);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
public static extern int RmEndSession(int dwSessionHandle);
}
"@ -ErrorAction Stop
function Restart-Explorer {
# Constants
$RM_SESSION_KEY_LEN = 32
# Prepare session
$sessionHandle = 0
$sessionKey = New-Object System.Text.StringBuilder ($RM_SESSION_KEY_LEN + 1)
# Start session
$start = [RestartManager]::RmStartSession([ref]$sessionHandle, 0, $sessionKey)
if ($start -ne 0) {
throw "RmStartSession failed with error code $start"
}
try {
# Register explorer.exe by full path
$explorerPath = Join-Path $env:WINDIR 'explorer.exe'
$files = @($explorerPath)
$reg = [RestartManager]::RmRegisterResources(
$sessionHandle, [uint32]$files.Count, $files, 0, [IntPtr]::Zero, 0, [IntPtr]::Zero
)
if ($reg -ne 0) {
throw "RmRegisterResources failed with error code $reg"
}
$needed = 0
$count = 0
$reasons = 0
# First call to get required size
$result = [RestartManager]::RmGetList($handle, [ref]$needed, [ref]$count, $null, [ref]$reasons)
if ($result -eq 234) { # 234 == ERROR_MORE_DATA
$array = New-Object RM_PROCESS_INFO[] $needed
$count = $needed
$result = [RestartManager]::RmGetList($handle, [ref]$needed, [ref]$count, $array, [ref]$reasons)
if ($result -eq 0) {
Write-Host "Porcesses using Explorer.exe"
foreach ($proc in $array) {
Write-Host "Process: $($proc.strAppName) (PID=$($proc.Process.dwProcessId))"
}
}
}
# Request shutdown of explorer (no special flags)
$sh = [RestartManager]::RmShutdown($sessionHandle, 0, [IntPtr]::Zero)
if ($sh -ne 0) {
throw "RmShutdown failed with error code $sh"
}
Start-Sleep -Milliseconds 500
# Request restart of explorer
$rs = [RestartManager]::RmRestart($sessionHandle, 0, [IntPtr]::Zero)
if ($rs -ne 0) {
throw "RmRestart failed with error code $rs"
}
Write-Host "Explorer restarted via Restart Manager. SessionKey=$($sessionKey.ToString())"
} finally {
# End session
[void][RestartManager]::RmEndSession($sessionHandle)
}
}
# Execute
Restart-Explorer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment