How to elevate privileges only when required?
Asked Answered
D

6

84

This question applies to Windows Vista!

I have an application which normally works without administrative privileges. There is one activity which does need administrative privilege but I don't want to start the application itself with higher privileges when I know most of time user wont even be using that feature.

I am thinking about certain method by which I can elevate the privileges of application on some event (such as press of a button). Example:

If user clicks this button then he is prompted with UAC dialog or consent. How can I do this?

Debility answered 21/2, 2009 at 14:13 Comment(0)
N
59

I don't believe that it is possible to elevate the currently running process. It is built into Windows Vista that administrator privileges are given to a process upon startup, as I understand. If you look at various programs that utilise UAC, you should see that they actually launch a separate process each time an administrative action needs to be performed (Task Manager is one, Paint.NET is another, the latter being a .NET application in fact).

The typical solution to this problem is to specify command line arguments when launching an elevated process (abatishchev's suggestion is one way to do this), so that the launched process knows only to display a certain dialog box, and then quit after this action has been completed. Thus it should hardly be noticeable to the user that a new process has been launched and then exited, and would rather appear as if a new dialog box within the same app has been opened (especially if you some hackery to make the main window of the elevated process a child of the parent process). If you don't need UI for the elevated access, even better.

For a full discussion of UAC on Vista, I recommend you see this very through article on the subject (code examples are in C++, but I suspect you'll need to use the WinAPI and P/Invoke to do most of the things in C# anyway). Hopefully you now at least see the right approach to take, though designing a UAC compliant program is far from trivial...

Neisse answered 21/2, 2009 at 14:50 Comment(4)
Is there any change with Windows 7 or does the answer "no, use new process" hold? Thanks...Johnie
No change with Windows 7 I'm afraid, sorry. (As far as I know, and I'm a regular user/developer on Win7.)Neisse
This is exactly how task manager does it. When you click the button to show tasks for all users it exists the current task manager then invokes another task manager with admin rights.Matelda
@NathanAdams Technically, it opens the new task manager first. Otherwise, what's doing the opening? :-)Candlewick
S
17

As it was said there:

Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";

will run the process as admin to do whatever you need with the registry, but return to your app with the normal privileges.

Styptic answered 21/2, 2009 at 14:23 Comment(8)
That involves spanning a new process. right? I was looking for elevating privileges of current process itself.Debility
Try use to Process.GetCurrentProcess()Styptic
You can't elevate a currently-running process.Roseboro
This is not true. You can change the Owner of the process and set the DACL and ACL values for the user giving them administrative powers....Rankins
@Nightforce2: could you please explain your proposed approach or at least point us to some resource on this subject?Leporide
The access token when run without elevation is given a restricted token by the function CreateRestrictedToken. The UAC moniker is used to verify human interaction, then elevates or enables the SID/Token group needed to run as a "500" group SID. You can change the restricted token using OpenProcessToken, GetTokenInformation, SetThreadToken, CreateWellknownSid, SetTokenInformation, AdjustTokenPrivileges(To add enabled SID's), CheckTokenMembership(Make sure new token has what you need), Cross-check your token with "IsTokenRestricted" to make sure your code is working as susposed to be.Rankins
Note: MS specifically undoc'd this API to prevent spread of malware. So no code examples will be given until they do or someone else gives this trick away. There are a few ways around this. Most common is "Runas" which is what they intended for people to use. This is best pointer I can give you w/o giving it away, specifically. Reading specifics about Vista/W7 SDK API and explainations will help you understand how UAC works and give you a good idea on how to work with it. MS said themselves this was never meant to be a security implementation, but a thorn in the side of malware developers.Rankins
@nightforce2: surely this would only work, if you already have administrative rights (i.e. you already are elevated). Otherwise AdjustTokenPrivileges etc will simply fail, no?Complacency
F
13

The following MSDN KB article 981778 describes how to 'self-elevate' an application:

http://support.microsoft.com/kb/981778

It contains downloadable samples in Visual C++, Visual C#, Visual Basic.NET.

This approach gets around the need to start a separate process, but in fact it is the original application that is restarted, running as an elevated user. Nevertheless this may still be very useful in some contexts where it is not practical to duplicate code in a separate executable.

To remove the elevation, you need to quit the application.

Farm answered 24/10, 2012 at 14:16 Comment(4)
Handy for a button, but when you want the same for a menu item, you're in for one really convoluted mess.Illation
@Todd You can find the code here: https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3Albertalberta
Answer's link is dead and comment's link points to a 2608 item long list.Williswillison
You can find it hereChaplet
M
5

You need a UAC moniker and the code to run elevated as a COM object.

See this question.

Documentation on MSDN.

Mayer answered 21/2, 2009 at 14:16 Comment(0)
I
3

Perhaps someone comes in handy this simple example:

using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Security.Principal;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    internal static class Program
    {
        private class Form1 : Form
        {
            internal Form1()
            {
                var button = new Button{ Dock = DockStyle.Fill };
                button.Click += (sender, args) => RunAsAdmin();
                Controls.Add(button);

                ElevatedAction();
            }
        }

        [STAThread]
        internal static void Main(string[] arguments)
        {
            if (arguments?.Contains("/run_elevated_action") == true)
            {
                ElevatedAction();
                return;
            }

            Application.Run(new Form1());
        }

        private static void RunAsAdmin()
        {
            var path = Assembly.GetExecutingAssembly().Location;
            using (var process = Process.Start(new ProcessStartInfo(path, "/run_elevated_action")
            {
                Verb = "runas"
            }))
            {
                process?.WaitForExit();
            }
        }

        private static void ElevatedAction()
        {
            MessageBox.Show($@"IsElevated: {IsElevated()}");
        }

        private static bool IsElevated()
        {
            using (var identity = WindowsIdentity.GetCurrent())
            {
                var principal = new WindowsPrincipal(identity);

                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
        }

    }
}
Interphase answered 5/3, 2018 at 16:39 Comment(0)
S
1

I know this is an old post, but this is in response to anyone else who comes across MarcP's suggestion. The msdn post he referenced indeed does restart the applications in all of the code examples. The code samples use the runas verb proposed already in other suggestions.

I downloaded the code to make sure, but this is from the original msdn article:

4. Click Yes to approve the elevation. Then, the original application restarts, running as an elevated administrator.
5. Close the application.

Suspect answered 16/4, 2013 at 19:46 Comment(1)
Can you add the MSDN link in question? I can't find a user called MarcP.Avebury

© 2022 - 2024 — McMap. All rights reserved.