Skip to content

Instantly share code, notes, and snippets.

@Frosthaven
Last active January 10, 2025 03:32
Show Gist options
  • Select an option

  • Save Frosthaven/5b9164751d298615797683f9d62cf610 to your computer and use it in GitHub Desktop.

Select an option

Save Frosthaven/5b9164751d298615797683f9d62cf610 to your computer and use it in GitHub Desktop.
# ABOUT ------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# AUTHOR: Frosthaven
# DISCORD: frosthaven
# DESCRIPTION: This is a powershell script that accomplishes the following:
# 1. Launches a process
# 2. Sets the affinity of the process to include or exclude specific cpu cores
# 3. Optionally monitors the process for hangs and kills it if it hangs
# 4. Optionally restarts the process if it hangs
# USAGE ------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# 1. Configure the script via the CONFIG section below.
# 2a. Launch via right click:
# - Right click the script and choosing "Run with PowerShell"
# 2b. Launch via customizable shortcut:
# - Right click the desktop
# - Choose New > Shortcut
# - Enter the following command into the target field (edit path as needed):
# powershell.exe -command "& 'C:\A path with spaces\MyScript.ps1'"
# Note: You can run this script after the process is already running if you
# need to. It will attach to the already running process and set the affinity.
# CONFIG -----------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Process Launch -----------------------
# The $exePath is the path to the executable you want to launch. The
# $processNameInTaskManager value is the name of the process as it appears in
# the task manager. The $sleepTime is the number of seconds to wait after
# launching the process before giving up on finding it in the task manager.
$exePath = "C:\Program Files (x86)\Steam\steamapps\common\Path of Exile 2\PathOfExileSteam.exe"
$processNameInTaskManager = "PathOfExileSteam"
$sleepTime = 4
# Core Affinity ------------------------
# I'm including two ways to do this below. The first way will include all
# available cores except the first two by starting the array after core 0 and 1.
# The second way will give more explicit control over EXACTLY which cores you
# want to have active. You can change which you want to enable/disable by
# changing which $enabledCores is commented out with a "#" character.
$coreCount = [Environment]::ProcessorCount
$enabledCores = 2..($coreCount - 1)
# $enabledCores = @(2, 3, 4)
# CPU Usage Auto-Kill ------------------
# Here you can set the script to automatically kill the process if it hangs, and
# optionally restart it. The $processHangTimeout is the number of seconds the
# script will wait for the process to respond before killing it.
$autoKillOnProcessHang = $true
$autoRestart = $true
$processHangTimeout = 5
# RUN SCRIPT -------------------------------------------------------------------
# ------------------------------------------------------------------------------
$host.privatedata.ProgressForegroundColor = "Green"
$host.privatedata.ProgressBackgroundColor = "Black"
# Start Process ------------------------
Clear-Host
$runningProcess = Get-Process -Name $processNameInTaskManager -ErrorAction SilentlyContinue
if ($runningProcess) {
Write-Host "Process running..."
} else {
Write-Host "Launching process..."
Start-Process $exePath -PassThru > $null
Start-Sleep -Seconds $sleepTime > $null
}
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host ""
# Wait for task manager entry ----------
$timeout = 10
$elapsedTime = 0
$activePID = $null
while ($null -eq $activePID -and $elapsedTime -lt $timeout) {
$runningProcess = Get-Process -Name $processNameInTaskManager -ErrorAction SilentlyContinue
if ($runningProcess) {
$activePID = $runningProcess.Id
} else {
Start-Sleep -Seconds 1
$elapsedTime++
}
}
if ($null -ne $activePID) {
# Set affinity ---------------------
Write-Host ""
Write-Host "Configuring affinity bitmask..."
$bitmask = 0
foreach ($core in $enabledCores) {
$bitmask = $bitmask -bor (1 -shl $core)
}
$processHandle = [System.Diagnostics.Process]::GetProcessById($activePID)
$processHandle.ProcessorAffinity = $bitmask
$disabledCores = 0..($coreCount - 1) | Where-Object { $_ -notin $enabledCores }
Write-Host ""
Write-Host "Processor affinity set:"
Write-Host " - Enabled cores: $($enabledCores -join ', ')"
Write-Host " - Disabled cores: $($disabledCores -join ', ')"
Write-Host ""
if (!$autoKillOnProcessHang) {
Write-Host "CPU monitor is disabled. Exiting now."
exit
}
# Kill on process hang -------------
$elapsedTime = 0
while ($elapsedTime -lt $processHangTimeout) {
$processHandleStillValid = [System.Diagnostics.Process]::GetProcesses() | Where-Object { $_.Id -eq $activePID }
if (-not $processHandleStillValid) {
Write-Host "Process handle is no longer valid. Exiting."
exit
}
$processIsResponding = $processHandle.Responding
if (!$processIsResponding) {
$elapsedTime++
} else {
$elapsedTime = 0
}
if ($elapsedTime -gt ($processHangTimeout / 2)) {
$host.privatedata.ProgressForegroundColor = "Yellow"
} elseif ($elapsedTime -gt ($processHangTimeout / 3 * 2)) {
$host.privatedata.ProgressForegroundColor = "Red"
} else {
$host.privatedata.ProgressForegroundColor = "Green"
}
Write-Progress -Activity "Monitoring $processNameInTaskManager.exe :: Process ID $activePID" -Status "Hang Detection Threshold ($elapsedTime/$processHangTimeout seconds)" -PercentComplete ($elapsedTime / $processHangTimeout * 100)
Start-Sleep -Seconds 1
}
Write-Host "Process hang detected..."
# Restart process ------------------
if ($autoRestart) {
Write-Host "Restarting..."
Stop-Process -Id $activePID
$thisScriptFile = $MyInvocation.MyCommand.Definition
Invoke-Expression "cmd /c start powershell.exe -ExecutionPolicy Bypass -File '$thisScriptFile'"
exit
} else {
Write-Host "Auto Restart is not enabled. Exiting now."
Stop-Process -Id $activePID
exit
}
} else {
Write-Host "Process did not start within the timeout period of $timeout seconds."
exit
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment