Repository navigation
Description
Prerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues.
- Refer to the FAQ.
- Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
Launching a process with the DETACHED_PROCESS flag of the WinAPI CreateProcess() function by design does so without a console, even for console-subsystem applications.
However, pwsh.exe assumes the presence of a console and quietly aborts if it cannot find one: exit code 0 is reported, and no WER (Windows Error Reporting) event is recorded in the Windows Application event log.
Note:
-
SCM, the Windows Service Control Manager, is an example of a component that starts (service) executables with
DETACHED_PROCESS; while usingpwsh.exeas a service executable is not a common use case, it is possible to implement a service via a.ps1script passed topwsh.exe -File- see this Stack Overflow post. -
There are two ways to fix this problem:
-
Report a nonzero exit code and log a WER event with a specific error message - this is what the repro below assumes.
-
Alternatively, allow PowerShell to run without a console: infer non-interactive mode in the absence of a console and prevent attempts to access console-specific features in a controlled manner (note that the
-noninteractiveCLI option does not currently do that).
-
-
The following repro code requires .NET 11+ / at least a PowerShell 7.7 preview version, due to use of the new
.StartDetachedproperty ofProcessStartInfo.
using namespace System.Diagnostics
$startTime = [System.DateTime]::Now
# Start PowerShell without a console (DETACHED_PROCESS)
# Note: Requires .NET 11+
[Process]::Start(
[ProcessStartInfo] @{
FileName = 'pwsh.exe'
Arguments = '-c "Start-Sleep 5"'
StartDetached = $true
}
) | Wait-Process -PassThru | Select-Object *Exit*
"Ran for $('{0:N1}' -f ([datetime]::Now - $startTime).TotalSeconds) secs." | Out-Host
# # As a crosscheck, use the following to provoke a crash that DOES create a WER event.
# $ps = Start-Process -PassThru conhost.exe (Get-Process -Id $PID).Path; Start-Sleep 2; $ps | Stop-Process
"Sleeping a little, to give a WER event time to show up" | Out-Host
1..5 | ForEach-Object { Write-Host -NoNewline .; Start-Sleep 1 }
Write-Host
# Report the resulting WER event, if any.
Get-WinEvent -FilterHashTable @{
ProviderName = 'Windows Error Reporting'
Id = 1001
Data = 'pwsh.exe' # matches the <Data Name="P1"> sub-element of <EventData>
StartTime = $startTime # events written since this [datetime] instance; supplemnt with `EndTime`, if needed
} | Format-ListThe offending parts of the source code:
PowerShell/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs
Lines 548 to 571 in 2725d6a
private static readonly Lazy<ConsoleHandle> _outputHandle = new Lazy<SafeFileHandle>(() => { // We use CreateFile here instead of GetStdWin32Handle, as GetStdWin32Handle will return redirected handles var handle = NativeMethods.CreateFile( "CONOUT$", (UInt32)(NativeMethods.AccessQualifiers.GenericRead | NativeMethods.AccessQualifiers.GenericWrite), (UInt32)NativeMethods.ShareModes.ShareWrite, (IntPtr)0, (UInt32)NativeMethods.CreationDisposition.OpenExisting, 0, (IntPtr)0); if (handle == NativeMethods.INVALID_HANDLE_VALUE) { int err = Marshal.GetLastWin32Error(); HostException e = CreateHostException(err, "RetreiveActiveScreenBufferConsoleHandle", ErrorCategory.ResourceUnavailable, ConsoleControlStrings.GetActiveScreenBufferHandleExceptionTemplate); throw e; } return new ConsoleHandle(handle, true); } ); PowerShell/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs
Lines 105 to 111 in 2725d6a
// These exceptions are caused by killing conhost.exe // 1236, network connection aborted by local system // 0x6, invalid console handle if (win32e.NativeErrorCode == 0x6 || win32e.NativeErrorCode == 1236) { return exitCode; }
Expected behavior
Ran for 10.0 secs.
.....
ExitCode HasExited ExitTime
-------- --------- --------
1 True <timestamp>
<tabular display of a WER event-log entry with a specific error message>Actual behavior
Ran for 0.3 secs.
.....
ExitCode HasExited ExitTime
-------- --------- --------
0 True <timestamp>
Get-WinEvent: foo.ps1:25
Line |
25 | Get-WinEvent -FilterHashTable @{
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| No events were found that match the specified selection criteria.That is:
- the
Start-Sleepcommand passed to-cnever got to execute - the exit code was unexpectedly
0 - no WER event was logged.
Error details
Environment data
PowerShell Core v7.7.0-preview.5 on WindowsVisuals
No response
Activity
iSazonov commentedon Nov 10, 2026
Apparently you need to run the detached process in Server Mode.
jessehouwing commentedon Nov 10, 2026
Server mode doesn't allow you to pass the start-up script as an argument from what I can tell.
mklement0 commentedon Nov 10, 2026
Good point, Jesse Houwing (@jessehouwing) - a run-given-code-then-exit CLI call is fundamentally different from putting
pwsh.exeinto a server mode.Apart from that, Ilya (@iSazonov): Among the various server modes:
-namedpipeservermodeappears to run normally.-servermodeand-shhservermodefail right away, but predictably so , given that they rely on stdin, which isn't available withDETACHED_PROCESS; confusingly, the exit code is0xFA0, however - no WER event is logged.-socketservermodecrashes after a couple of seconds, via.FailFast()(which creates 2 .NET event-log events plus a WER one), due toFailed to create an instance of RemoteSessionHyperVSocketServe, with exit code0x80131623.