23

I want to start a child process (indeed the same, console app) with elevated privileges but with hidden window.

I do next:

var info = new ProcessStartInfo(Assembly.GetEntryAssembly().Location)
{
    UseShellExecute = true, // !
    Verb = "runas", 
};

var process = new Process
{
    StartInfo = info
};

process.Start();

and this works:

var identity = new WindowsPrincipal(WindowsIdentity.GetCurrent());
identity.IsInRole(WindowsBuiltInRole.Administrator); // returns true

But UseShellExecute = true creates a new window and I also I can't redirect output.

So when I do next:

var info = new ProcessStartInfo(Assembly.GetEntryAssembly().Location)
{
    RedirectStandardError = true,
    RedirectStandardOutput = true,
    UseShellExecute = false, // !
    Verb = "runas"
};

var process = new Process
{
    EnableRaisingEvents = true,
    StartInfo = info
};

DataReceivedEventHandler actionWrite = (sender, e) =>
{
    Console.WriteLine(e.Data);
};

process.ErrorDataReceived += actionWrite;
process.OutputDataReceived += actionWrite;

process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();

This doesn't elevate privileges and code above returns false. Why??

abatishchev
  • 98,240
  • 88
  • 296
  • 433
  • BTW, you can write `DataReceivedEventHandler actionWrite = ...` and `process.ErrorDataReceived += actionWrite`. – SLaks Aug 29 '10 at 19:35
  • Can you test using UseShellExecute = true, Verb = "runas", and ErrorDataReceived events as @SLaks comment ? – Kiquenet Oct 15 '14 at 17:02

3 Answers3

22

ProcessStartInfo.Verb will only have an effect if the process is started by ShellExecuteEx(). Which requires UseShellExecute = true. Redirecting I/O and hiding the window can only work if the process is started by CreateProcess(). Which requires UseShellExecute = false.

Well, that's why it doesn't work. Not sure if forbidding to start a hidden process that bypasses UAC was intentional. Probably. Very probably.

Check this Q+A for the manifest you need to display the UAC elevation prompt.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thank you very much for WinAPI behind-the-scene description. How do you think is it possible to get elevated privileges on demand for a process with hidden window? Or this is mutually exclusive things? – abatishchev Aug 30 '10 at 13:10
  • And is it possible to switch on/off using manifest? I.e. when I start my app first time (manually) - don't use a manifest, when second (programmatically) - force to use. – abatishchev Aug 30 '10 at 13:12
  • Starting a process with elevated privileges without the user knowing about it is not possible. You need a separate .exe so that it has its own manifest. Basically you only need the Main() method. – Hans Passant Aug 30 '10 at 13:18
  • I don't want to hide process launch from user, I still need UAC confirm from him, I just want to hide started process window. I think this isn't possible too, right? – abatishchev Aug 30 '10 at 14:50
  • 2
    Hmm... this is rather frustrating. – tofutim May 21 '13 at 00:48
12

In my case, it was ok to get the outputs once the elevated child process is done. Here's the solution I came up. It uses a temporary file :

var output = Path.GetTempFileName();
var process = Process.Start(new ProcessStartInfo
{
    FileName = "cmd",
    Arguments = "/c echo I'm an admin > " + output, // redirect to temp file
    Verb = "runas", // UAC prompt
    UseShellExecute = true,
});
process.WaitForExit();
string res = File.ReadAllText(output);
// do something with the output
File.Delete(output);
tpol
  • 910
  • 10
  • 16
  • this actually appears to be working for me. convoluted details (windows 10, F#) - gist at https://gist.github.com/ImaginaryDevelopment/f4bc33ae75bdf29e5aad8fd4045f193d – Maslow Dec 13 '16 at 16:44
  • The accepted answer is an explanation, this is a solution.. +1 – caesay Jun 10 '17 at 03:26
0

Check this answer.

This seems to provide a workaround. But I recommend to try other methods like Named Pipes when you have access to source code of the child process.

Community
  • 1
  • 1
Masood Khaari
  • 2,911
  • 2
  • 23
  • 40
  • 1
    I haven't tested the UAC article approach, though it contains a sample by itself. But if you mean a sample for Named Pipes, you can easily find many of them (like [this](http://stackoverflow.com/questions/13806153/example-of-named-pipes) or [this](http://www.codeproject.com/Tips/492231/Csharp-Async-Named-Pipes)) with a little search. The point is that like I/O redirection, you can use textual streams with Named Pipes too, to send and receive data (even if the two processes reside on different machines). Of course you have to deal with some nuances to get a fully working application. – Masood Khaari Aug 11 '14 at 13:29
  • @abatishchev IMHO, better using Trace to File, not redirect output, verb = runas. Named Pipes is much more complex and complex to debugging easy. – Kiquenet Oct 15 '14 at 17:13