If you want to launch a visible console window that executes a script file and stays open (enters an interactive session after the script exits):
Do NOT use the PowerShell SDK and its PowerShell
.NET class: Its purpose is programmatic control of PowerShell commands, not visible, interactive execution.
Instead, use the general-purpose Process
class to create a child process that launches the PowerShell CLI in a visible console window (by default):
System.Diagnostics.Process.Start(
"powershell.exe", // The Windows PowerShell CLI
@"-ExecutionPolicy Bypass -NoExit -NoLogo -File C:\Users\username\Desktop\test.ps1 5"
).WaitForExit();
Note how the argument(s) to pass to the script file are specified after the script-file path (5
in this example) - be sure to double-quote them as needed, such as when they contain embedded spaces.
Since everything after a -File
(-f
) is interpreted as the script-file path and the arguments to pass to the script, be sure to place these arguments last on the command line.
Alternatively, if you're creating a .NET Core / .NET 5+ application, you may specify all arguments individually, in which case .NET takes care of any required double-quoting for you:
System.Diagnostics.Process.Start(
"powershell.exe", // The Windows PowerShell CLI
new string[] {
"-ExecutionPolicy",
"Bypass",
"-NoExit",
"-NoLogo",
"-File",
@"C:\Users\jdoe\Desktop\pg\pg.ps1",
"5" // Pass-through arguments.
}
).WaitForExit();
Pitfall:
-NoExit
is not honored if the script file passed to -File
cannot be found.
- This contrasts with passing a piece of PowerShell source code to the
-Command
(-c
) parameter, where -NoExit
is honored, even if execution of the source code results in errors).
- This discrepancy is arguably a bug and has been reported in GitHub issue #10471.
The upshot is that if you launch the process not from an existing console window, a console window is created on demand, which automatically closes shortly after, namely after PowerShell has reported the error due to not finding the specified script file, making it all but impossible to see what happened.
The workaround is to use the -Command
parameter instead, which keeps the window open unconditionally:
// Again, passing arguments individually is an option in .NET Core / .NET 5+
System.Diagnostics.Process.Start(
"powershell.exe", // The Windows PowerShell CLI
@"-ExecutionPolicy Bypass -NoExit -NoLogo -Command & C:\Users\username\Desktop\test.ps1 5"
).WaitForExit();
Note the use of &
, the call operator, to invoke the script (which isn't strictly necessary in this case, but generally is if the script-file path is quoted and/or contains variable references).
Also note that using -Command
changes how the pass-through arguments are interpreted, which may or may not cause problems (not with a simple argument such as 5
); in short: after command-line parsing, during which syntactic (unescaped) "
chars. are stripped, PowerShell then interprets the resulting arguments as PowerShell source code, subjecting them to an additional layer of interpretation - see this answer for more information.