@@ -1677,7 +1677,7 @@ public SwitchParameter LoadUserProfile
1677
1677
private SwitchParameter _loaduserprofile = SwitchParameter . Present ;
1678
1678
1679
1679
/// <summary>
1680
- /// Starts process ina new window.
1680
+ /// Starts process inthe current console window.
1681
1681
/// </summary>
1682
1682
[ Parameter ( ParameterSetName = "Default" ) ]
1683
1683
[ Alias ( "nnw" ) ]
@@ -1965,7 +1965,9 @@ protected override void BeginProcessing()
1965
1965
1966
1966
startInfo . WindowStyle = _windowstyle ;
1967
1967
1968
- if ( _nonewwindow )
1968
+ // When starting a process as another user, the 'CreateNoWindow' property value is ignored and a new window is created.
1969
+ // See details at https://learn.microsoft.com/dotnet/api/system.diagnostics.processstartinfo.createnowindow?view=net-9.0#remarks
1970
+ if ( _nonewwindow && _credential is null )
1969
1971
{
1970
1972
startInfo . CreateNoWindow = _nonewwindow ;
1971
1973
}
@@ -2413,33 +2415,60 @@ private static byte[] ConvertEnvVarsToByteArray(StringDictionary sd)
2413
2415
2414
2416
private void SetStartupInfo ( ProcessStartInfo startinfo , ref ProcessNativeMethods . STARTUPINFO lpStartupInfo , ref int creationFlags )
2415
2417
{
2416
- bool hasRedirection = false ;
2418
+ // If we are starting a process using the current console window, we need to set its standard handles
2419
+ // explicitly when they are not redirected because otherwise they won't be set and the new process will
2420
+ // fail with the "invalid handle" error.
2421
+ //
2422
+ // However, if we are starting a process with a new console window, we should not explicitly set those
2423
+ // standard handles when they are not redirected, but instead let Windows figure out the default to use
2424
+ // when creating the process. Otherwise, the standard input handles of the current window and the new
2425
+ // window will get weirdly tied together and cause problems.
2426
+ bool hasRedirection = startinfo . CreateNoWindow
2427
+ || _redirectstandardinput is notnull
2428
+ || _redirectstandardoutput is notnull
2429
+ || _redirectstandarderror is notnull ;
2430
+
2417
2431
// RedirectionStandardInput
2418
2432
if ( _redirectstandardinput != null )
2419
2433
{
2420
- hasRedirection = true ;
2421
2434
startinfo . RedirectStandardInput = true ;
2422
2435
_redirectstandardinput = ResolveFilePath ( _redirectstandardinput ) ;
2423
2436
lpStartupInfo . hStdInput = GetSafeFileHandleForRedirection ( _redirectstandardinput , FileMode . Open ) ;
2424
2437
}
2438
+ else if ( startinfo . CreateNoWindow )
2439
+ {
2440
+ lpStartupInfo . hStdInput = new SafeFileHandle (
2441
+ ProcessNativeMethods . GetStdHandle ( - 10 ) ,
2442
+ ownsHandle : false ) ;
2443
+ }
2425
2444
2426
2445
// RedirectionStandardOutput
2427
2446
if ( _redirectstandardoutput != null )
2428
2447
{
2429
- hasRedirection = true ;
2430
2448
startinfo . RedirectStandardOutput = true ;
2431
2449
_redirectstandardoutput = ResolveFilePath ( _redirectstandardoutput ) ;
2432
2450
lpStartupInfo . hStdOutput = GetSafeFileHandleForRedirection ( _redirectstandardoutput , FileMode . Create ) ;
2433
2451
}
2452
+ else if ( startinfo . CreateNoWindow )
2453
+ {
2454
+ lpStartupInfo . hStdOutput = new SafeFileHandle (
2455
+ ProcessNativeMethods . GetStdHandle ( - 11 ) ,
2456
+ ownsHandle : false ) ;
2457
+ }
2434
2458
2435
2459
// RedirectionStandardError
2436
2460
if ( _redirectstandarderror != null )
2437
2461
{
2438
- hasRedirection = true ;
2439
2462
startinfo . RedirectStandardError = true ;
2440
2463
_redirectstandarderror = ResolveFilePath ( _redirectstandarderror ) ;
2441
2464
lpStartupInfo . hStdError = GetSafeFileHandleForRedirection ( _redirectstandarderror , FileMode . Create ) ;
2442
2465
}
2466
+ else if ( startinfo . CreateNoWindow )
2467
+ {
2468
+ lpStartupInfo . hStdError = new SafeFileHandle (
2469
+ ProcessNativeMethods . GetStdHandle ( - 12 ) ,
2470
+ ownsHandle : false ) ;
2471
+ }
2443
2472
2444
2473
if ( hasRedirection )
2445
2474
{
@@ -2881,6 +2910,9 @@ internal struct JOBOBJECT_BASIC_PROCESS_ID_LIST
2881
2910
2882
2911
internal static class ProcessNativeMethods
2883
2912
{
2913
+ [ DllImport ( PinvokeDllNames . GetStdHandleDllName , SetLastError = true ) ]
2914
+ public static extern IntPtr GetStdHandle ( int whichHandle ) ;
2915
+
2884
2916
[ DllImport ( PinvokeDllNames . CreateProcessWithLogonWDllName , CharSet = CharSet . Unicode , SetLastError = true , ExactSpelling = true ) ]
2885
2917
[ return : MarshalAs ( UnmanagedType . Bool ) ]
2886
2918
internal static extern bool CreateProcessWithLogonW ( string userName ,