114

I have a Visual Studio Windows app project. I've added code to download an installer update file. The installer after it has finished downloading would need administrator privileges to run. I have added a manifest file.

When user clicks on the DownloadUpdate.exe, UAC prompts the user for Admin permissions. So I assumed that all processes created and called within DownloadUpdate.exe will run in admin capacity. So I made the setup call my downloaded file with the following code:

Process p = new Process();
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.FileName = strFile;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
dtb
  • 213,145
  • 36
  • 401
  • 431
RPS
  • 1,201
  • 2
  • 10
  • 4
  • 1
    No you can't assume all processes run from DownloadUpdater.exe are run in admin mode. In fact, that would be a terrible security breach. If you run another process that needs administrator rights, the user will be prompt again. – Waldo Bronchart Mar 03 '11 at 13:26

9 Answers9

90

Try this:

//Vista or higher check
if (System.Environment.OSVersion.Version.Major >= 6)
{
   p.StartInfo.Verb = "runas";
}

Alternatively, go the manifest route for your application.

default
  • 11,485
  • 9
  • 66
  • 102
Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • 9
    note that this answer will probably not work without `p.StartInfo.UseShellExecute = true;`. – anion Oct 22 '20 at 18:55
  • 1
    @anion I had to include `UseShellExecute = true` to make .Net 6 program to successfully start another program as admin. In .Net Framework 4.7.1 I didn't need to include it. – OSA413 Jun 08 '22 at 18:07
58

First of all you need to include in your project

using System.Diagnostics;

After that you could write a general method that you could use for different .exe files that you want to use. It would be like below:

public void ExecuteAsAdmin(string fileName)
{
    Process proc = new Process();
    proc.StartInfo.FileName = fileName;
    proc.StartInfo.UseShellExecute = true;
    proc.StartInfo.Verb = "runas";
    proc.Start();
}

If you want to for example execute notepad.exe then all you do is you call this method:

ExecuteAsAdmin("notepad.exe");
Tiago S
  • 1,299
  • 23
  • 23
drgmak
  • 1,135
  • 10
  • 13
  • How to execute also the pop up yes or no on administrator and if the bat file exectute it and need a press key to close. – Detective7 Oct 26 '21 at 14:03
27

This is a clear answer to your question: How do I force my .NET application to run as administrator?

Summary:

Right Click on project -> Add new item -> Application Manifest File

Then in that file change a line like this:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

Compile and run!

Community
  • 1
  • 1
MSajjadi
  • 3,809
  • 3
  • 23
  • 20
23
var pass = new SecureString();
pass.AppendChar('s');
pass.AppendChar('e');
pass.AppendChar('c');
pass.AppendChar('r');
pass.AppendChar('e');
pass.AppendChar('t');
Process.Start("notepad", "admin", pass, "");

Works also with ProcessStartInfo:

var psi = new ProcessStartInfo
{
    FileName = "notepad",
    UserName = "admin",
    Domain = "",
    Password = pass,
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true
};
Process.Start(psi);
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 5
    Ok, but why do you use AppendChar? Can't you write `pass="secret"` ? – Jet Mar 27 '13 at 20:02
  • 7
    @Jet no as it takes a securestring not a string and those are never meant to be available as 1 unencrypted chunk in memory – Ronan Thibaudau May 12 '15 at 06:31
  • Assuming your password is `password`, you can do `for (int x = 0; x < password.Length; x++) { pass.AppendChar(password[x]); }` – Mark Richman Jun 10 '16 at 15:23
  • 7
    @MarkRichman that defeats the purpose of using a `SecureString`. -- You're supposed to read them in one char at a time from somewhere (i.e. a keyboard, or an encrypted source, etc.). -- If you have an actual `string` that contains the data anyway, then it's not secure. – BrainSlugs83 Jun 26 '17 at 23:28
  • @MarkRichman `password.ForEach(pass.AppendChar)` looks cleaner. – Mikael Dúi Bolinder Mar 01 '19 at 11:49
18

This works when I try it. I double-checked with two sample programs:

using System;
using System.Diagnostics;

namespace ConsoleApplication1 {
  class Program {
    static void Main(string[] args) {
      Process.Start("ConsoleApplication2.exe");
    }
  }
}

using System;
using System.IO;

namespace ConsoleApplication2 {
  class Program {
    static void Main(string[] args) {
      try {
        File.WriteAllText(@"c:\program files\test.txt", "hello world");
      }
      catch (Exception ex) {
        Console.WriteLine(ex.ToString());
        Console.ReadLine();
      }
    }
  }
}

First verified that I get the UAC bomb:

System.UnauthorizedAccessException: Access to the path 'c:\program files\test.txt' is denied.
// etc..

Then added a manifest to ConsoleApplication1 with the phrase:

    <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

No bomb. And a file I can't easily delete :) This is consistent with several previous tests on various machines running Vista and Win7. The started program inherits the security token from the starter program. If the starter has acquired admin privileges, the started program has them as well.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Can't delete? Please elaborate, this sounds familiar. – Arlen Beiler Mar 22 '13 at 12:45
  • @ArlenBeiler: he probably means an embedded manifest in the application versus a .exe.manifest file on disk side-by-side to the executable. – Thomas Weller Oct 16 '14 at 20:08
  • @ThomasW. I think he is referring to the test file requiring administrator permissions to be deleted. I have run into this several times and usually requires going into the security tab and changing some settings, if I recall correctly. I think I eventually figured out a way. Elevated command prompt might also work, but be careful. Time sometimes brings answers. :-) – Arlen Beiler Oct 17 '14 at 01:35
5

Here is an example of run process as administrator without Windows Prompt

  Process p = new Process();
  p.StartInfo.FileName = Server.MapPath("process.exe");
  p.StartInfo.Arguments = "";
  p.StartInfo.UseShellExecute = false;
  p.StartInfo.CreateNoWindow = true;
  p.StartInfo.RedirectStandardOutput = true;
  p.StartInfo.Verb = "runas";
  p.Start();
  p.WaitForExit();
Hassan Nazeer
  • 357
  • 3
  • 5
  • This solved my problem! The prompt would come up from others' answers. The combination of UseShellExecute, CreateNoWindow and RedirectStandardOutput stopped that for me. – Blake Thingstad Feb 01 '17 at 21:45
  • 4
    This doesn't run as Administrator. If you add a manifest and request elevated permissions, it still won't work. – MtnManChris Jan 24 '18 at 22:31
  • it is also not working, It asked me to enter admin password while uninstalling window service from application – Shyam sundar shah May 30 '21 at 11:39
3
 Process proc = new Process();                                                              
                   ProcessStartInfo info = 
                   new ProcessStartInfo("Your Process name".exe, "Arguments");
                   info.WindowStyle = ProcessWindowStyle.Hidden;
                   info.UseShellExecute =true;
                   info.Verb ="runas";
                   proc.StartInfo = info;
                   proc.Start();
Spike0xff
  • 1,246
  • 1
  • 15
  • 24
chirag pathak
  • 121
  • 1
  • 14
2

Use this method:

public static int RunProcessAsAdmin(string exeName, string parameters)
    {
        try {
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.UseShellExecute = true;
            startInfo.WorkingDirectory = CurrentDirectory;
            startInfo.FileName = Path.Combine(CurrentDirectory, exeName);
            startInfo.Verb = "runas";
            //MLHIDE
            startInfo.Arguments = parameters;
            startInfo.ErrorDialog = true;

            Process process = System.Diagnostics.Process.Start(startInfo);
            process.WaitForExit();
            return process.ExitCode;
        } catch (Win32Exception ex) {
            WriteLog(ex);
            switch (ex.NativeErrorCode) {
                case 1223:
                    return ex.NativeErrorCode;
                default:
                    return ErrorReturnInteger;
            }

        } catch (Exception ex) {
            WriteLog(ex);
            return ErrorReturnInteger;
        }
    }

Hope it helps.

etrupja
  • 2,710
  • 6
  • 22
  • 37
0

You probably need to set your application as an x64 app.

The IIS Snap In only works in 64 bit and doesn't work in 32 bit, and a process spawned from a 32 bit app seems to work to be a 32 bit process and the same goes for 64 bit apps.

Look at: Start process as 64 bit

Community
  • 1
  • 1