Running PowerShell Scripts Continuously After Terminal Closes on Windows
Background
Working with background tasks on Linux using nohup led to an investigation of whether PowerShell could maintain script execution after the terminal window is closed.
Investigation
The following solutions were explored based on community discussions. A test script was created that prints incrementing numbers every second.
# ContinuousPrinter.ps1
# Initialize counter variable
$counter = 0
# Loop indefinitely until manually stopped
while ($true) {
# Output current counter value
Write-Output "Current number: $counter"
# Pause execution for one second
Start-Sleep -Seconds 1
# Increment the counter
$counter++
}
Start-Process Method
Using pwsh (PowerShell 7), execute commands without visible windows. While functional, this approach has management limitations.
Start-Process pwsh.exe -RedirectStandardOutput ./output.log -ArgumentList ".\ContinuousPrinter.ps1" -WindowStyle Hidden
Start-Job Approach
Start-Job provides background execution capability but terminates when the console closes. Unlike Linux's nohup, this doesn't fully detach the process from the terminal session.
Combining Start-Process with hidden window styling was attempted, using a blocking Read-Host call to prevent immediate process termination. However, this approach did not yield successful results for persistent execution.
Converting to Windows Service
Two popular utilities enable running applications as Windows services: procrun and nssm.
Using NSSM
The Non-Sucking Service Manager (nssm) provides a streamlined way to wrap executables as services. Execute commands from the nssm installation directory.
# Define service configuration
$serviceName = 'ContinuousPrinterService'
# Locate PowerShell 7 executable
$powershellPath = (Get-Command pwsh).Source
# Specify script to run as service
$scriptPath = 'C:\Scripts\ContinuousPrinter.ps1'
# Configure service arguments
$serviceArgs = '-ExecutionPolicy Bypass -NoProfile -File "{0}"' -f $scriptPath
# Register the service
.\nssm install $serviceName $powershellPath $serviceArgs
.\nssm set $serviceName AppStdout "C:\Logs\stdout.log"
.\nssm set $serviceName AppStderr "C:\Logs\stderr.log"
# Verify service registration
Get-Service $serviceName
Thiss method provides satisfactory results, though some users report that PowerShell startup messages appear in logs while script output may require additional configuraton to capture properly.
Considerations
Windows command-line functionality for background execution proves more complex compared to Linux equivalents. While Linux provides straightforward utilities like nohup and disown, Windows requires alternative approaches or third-party tools. Use cases may be limited, but achieving persistent background execution on Windows is certainly possible with the right tools.