Otávio Caldonazo's helpful answer provides an effective solution, but it's worth explaining a few things:
Unless there are security concerns (someone having placed a nonstandard, malicious cmd.exe
/ powershell.exe
executable in a folder listed in the %PATH%
/ $env:PATH
environment variable that preempts the standard executables), it is simpler to use the executable file name alone, i.e., just cmd.exe
/ powershell.exe
- this also avoids problems with non-standard Windows installations whose root is not C:\Windows
.
- Also, given that you're specifying a full path via
.FileName
, the .WorkingDirectory
property is effectively ignored with .Verb
set to runas
, because .WorkingDirectory
then doesn't actually set the working directory, but specifies where to find the executable, if specified by name only - however, lookups in %PATH%
/ $env:PATH
are still performed.
While the /c
parameter to pass a command to the shell invoked happens to work with PowerShell's CLI too, PowerShell generally use sigil -
to prefix parameter names; thus,
-c
(short for -Command
) is the better choice.
- Additionally, given that PowerShell loads its
$PROFILE
initialization file by default (even when invoked with -Command
or -File
, even though that is generally undesirable), it's best to use -NoProfile -Command ...
instead.
Generally - if you don't need elevation (running as an admin) - as an alternative to the - slow - creation of a child process via powershell.exe
, consider use of the PowerShell SDK (API), which enables faster in-process execution while also enabling more fine-grained capturing of output streams (which you don't seem to be interested in in your particular scenario; while System.Diagnostics.ProcessStartInfo
allows you to capture stdout and stderr output via the .RedirectStandardOutput
and .RedirectStandardError
properties, note that PowerShell has additional output streams).
Based on the above, I suggest doing the following:
var proc = new System.Diagnostics.ProcessStartInfo();
proc.UseShellExecute = true;
proc.Verb = "runas";
proc.FileName = @"powershell.exe";
proc.Arguments = "-NoProfile -Command " + command;
proc.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
var p = System.Diagnostics.Process.Start(proc);
p.WaitForExit();
Or, more concisely:
using System;
using System.Diagnostics;
var proc = new ProcessStartInfo()
{
UseShellExecute = true,
Verb = "runas",
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "powershell.exe",
Arguments = "-NoProfile -Command " + command
};
Process.Start(proc).WaitForExit();