Elevating privileges doesn't work with UseShellExecute=false

18,014

Solution 1

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.

Solution 2

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);
Share:
18,014
abatishchev
Author by

abatishchev

This is my GUID. There are many like it but this one is mine. My GUID is my best friend. It is my life. I must master it as I must master my life. Without me, my GUID is useless. Without my GUID I am useless.

Updated on June 27, 2022

Comments

  • abatishchev
    abatishchev almost 2 years

    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
    abatishchev over 13 years
    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
    abatishchev over 13 years
    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.
  • user1703401
    user1703401 over 13 years
    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.
  • abatishchev
    abatishchev over 13 years
    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?
  • tofutim
    tofutim almost 11 years
    Hmm... this is rather frustrating.
  • Masood Khaari
    Masood Khaari over 9 years
    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 or this) 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.
  • Kiquenet
    Kiquenet over 9 years
    @abatishchev IMHO, better using Trace to File, not redirect output, verb = runas. Named Pipes is much more complex and complex to debugging easy.
  • Nicolas Fall
    Nicolas Fall over 7 years
    this actually appears to be working for me. convoluted details (windows 10, F#) - gist at gist.github.com/ImaginaryDevelopment/…
  • caesay
    caesay almost 7 years
    The accepted answer is an explanation, this is a solution.. +1