0

how can i request admin rights at runtime in a winforms C# application? I have seen some installers asking for admin rights after selecting 'install for all users' (at runtime).

I have seen some answers on other questions saying it is impossible to request admin at runtime. I have tried this code:

System.AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

but it requires current user to be admin to gain the rights.

are there any other methods to request admin at runtime? (please dont suggest creating a manifest file thank you)

jebac pis
  • 39
  • 5
  • 1
    A process runs under a user identity. This identity cannot change once the process has started (ignoring things like impersonation for a moment). What those installers do (and what you could do as well) is launch another process with administrative privileges. This can be done without a manifest, even though that's the preferred way; [see also](https://stackoverflow.com/q/133379/4137916). – Jeroen Mostert Jan 23 '23 at 13:37
  • is there any way i can request admin rights at startup depending on a if statement? Restarting application and creating a check for a memory variable seems easier and i dont want my program to be shipped with multiple exes – jebac pis Jan 23 '23 at 13:43
  • You don't need multiple executables, you could launch the same executable you started with (if not admin, relaunch and exit; you can do this conditional on a command line argument). You can't *directly* go into administrative mode without a check and relaunching, because that would need to happen before your process even starts. A process not running as an administrator elevating itself (even if only by user action) would open up many possibilities for privilege escalation vulnerabilities, so MS has wisely chosen to not make that possible. – Jeroen Mostert Jan 23 '23 at 13:47
  • How can i ask for rights at startup if there are any arguments (i already have a argument check prototype) I dont understand what do you mean by 'you can do this conditional on a command line argument'. How exactly could i do that? – jebac pis Jan 23 '23 at 13:57
  • From your non-elevated application, launch `myapp.exe /admin` with the `runas` method. In your startup, check if `/admin` was passed and you are running as an administrator; if not, give an error and exit since something clearly went wrong, otherwise, proceed. You don't technically need the `/admin` argument if the main application will exit immediately and have the child take over, but otherwise it's convenient for the child to know it's doing work on behalf of the parent. – Jeroen Mostert Jan 23 '23 at 14:06
  • I have found a solution and posted it in answers. thanks for the links – jebac pis Jan 23 '23 at 14:27

2 Answers2

0

You can't add administrator rights to a running process that has already started. It either has admin rights for the life of the process from the moment it starts up, or it doesn't.

To get around this, there are three common strategies here, in order of preference:

  1. Rebuild the exe according to best practices, so it no longer needs administrator access. This isn't always an option, but it's possible a lot more often than people realize. The biggest culprit here is writing into the Program Files folder; if you can instead change the application to save files in the Application Data folder you may find you don't need administrator access at all.
  2. Split the app's functions to a second (or more) exe file, where the main exe calls into the additional exe(s) for any function requiring elevation.
  3. Set your app to ALWAYS prompt for administrator rights. You can do this in the properties for the .exe file, without modifying any code in the application itself (You will need to modify your installer).
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • It IS actually possible i have posted an answer with the solution. The trick is you restart the application using ProcessStartInfo and using the `startInfo.UseShellExecute = true;` which forces the program to restart and ask for administrative rights – jebac pis Jan 23 '23 at 15:01
  • 1
    @jebacpis No, your solution kills the running process and starts a new process. That would be a 4th strategy, but it's **not common.** The reason it's not common is it's either inferior to strategy #1 in the case where you know you'll always need admin rights anyway, or it results in resetting all of the application state in cases where you might not need to do the test until later, which makes it inferior to strategy #2. – Joel Coehoorn Jan 23 '23 at 15:02
  • The “not common” approach is so widely used by Visual Studio/Process Explorer and many other commonly used tools, so I wonder how come it is not common. – Lex Li Jan 23 '23 at 15:43
  • @LexLi Because of the reasons explained in the comment. When it is used, it's typically in applications that expect to run as administrator all the time, but are distributed without an installer to set the property on the application's exe. Process Explorer is a good example there. – Joel Coehoorn Jan 23 '23 at 15:46
  • Like I said, part of your comment makes no sense and real world examples are there against your reasoning. – Lex Li Jan 23 '23 at 15:49
  • Reordered the list in the order in which the options should be attempted. Mentioning it here, because it impacts the #s used in the prior comment. – Joel Coehoorn Jan 23 '23 at 16:59
-2

I have discovered how to ask for administrator rights at runtime.

Here's how to do it: add this class to your Program.cs file (alternatively, create standalone static bool)

public static class RequestAdministrator
{
    public static bool request = false;
}

Now you want to check at startup, if your program has been ran with any arguments.

static void Main(string[] args)
{
    if (args.Count() == 0 /* or args[0].ToString() == "admin"*/)
    {
        RequestAdministrator.request = false;

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
    else
    {
        // request admin
        RequestAdministrator.request = true;

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

And then place this code wherever you want your program to request admin rights. It restarts the program with "admin" argument, allowing you to put additional code in the if statement (e.g. load the same file from previous instance)

//this will try to get the administrator rights if the user is an admin                           
System.AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)

if (IsAdministrator() == false)
{
            //Init a new instance of the program
            ProcessStartInfo startInfo = new ProcessStartInfo(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName, "admin");
            startInfo.UseShellExecute = true;
            startInfo.Verb = "runas";
            System.Diagnostics.Process.Start(startInfo);
            //no need for Application.Exit()
}

public static bool IsAdministrator()
{
    var identity = WindowsIdentity.GetCurrent();
    var principal = new WindowsPrincipal(identity);

    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}

In the end, you can use this code to see if the admin right have been requested (you can use IsAdministrator() as well to determine if user declined admin privileges)

if (RequestAdministrator.request == false)
{
    // continue without rights (user ran the exe)

    // your code here

    // Step1 step1 = new Step1();
    // this.Controls.Add(step1);
    // step1.Show();
}
else
{
    // request true (restarted with arguments)

    // your code here

    // Step2 step2 = new Step2();
    // this.Controls.Add(step2);
    // step2.Show();
}

Result

program asking for admin

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
jebac pis
  • 39
  • 5
  • If you're gonna do this, why not set the exe's properties to just always require administrator rights? – Joel Coehoorn Jan 23 '23 at 15:02
  • This will create a new process from the same executable, which is not the same as having an existing procesing getting administrator rights. For example, all previous state of the (non-admin) process will be gone, when restartet. Unless you take manual/explicit measures to save such state and manually "reload" it in the restartet "admin" process. (Think of Window position, opened files, etc.) – Christian.K Jan 23 '23 at 15:06
  • I didn't downvote. And yes you could do as you suggested. (But still, technically, it is not the same as giving yourself (as in the currently running process) administrator rights.) – Christian.K Jan 23 '23 at 15:11
  • It was down voted probably because people in your situation should use a proper installer technology instead. The sample code you shared doesn’t look clean enough and also lacks of completeness. – Lex Li Jan 23 '23 at 15:46