Click here to Skip to main content
15,860,844 members
Articles / Programming Languages / C# 3.5

Getting Elevated Privileges on Demand using C#

Rate me:
Please Sign up or sign in to vote.
4.96/5 (18 votes)
9 Sep 2010CPOL3 min read 201.8K   3.5K   76   16
The article reveals the details of how to execute only portion of application code base under elevated privileges

Introduction

With going on stage Windows Vista and Windows 7 later on and new user security paradigm introduction (UAC), it becomes necessary to support such behavior when elevated privileges are required to perform some portion of code base, i.e., writing to registry, modifying files under system protected folders, etc.

So, in general, there are two ways to implement such behavior:

  • Embed a manifest info executable to indicate that the application requires elevated privileges from the beginning and can't be run without gaining administrative rights at all. Here's an example of such manifest:
    XML
    <?xml version="1.0" encoding="utf-8" ?> 
    <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" 
    	xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" 
    	xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <assemblyIdentity version="1.0.0.0" name="MyApplication" />
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
            <security>
                <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                    <requestedExecutionLevel level="requireAdministrator" 
    		uiAccess="false" />
                </requestedPrivileges>
            </security>
        </trustInfo>
    </asmv1:assembly>  
  • Separate the code base into two parts: the first doesn't require elevated privileges and the second - does, so call one from another. The article covers a case when the calling application is a console with a number of command line arguments: some of them can be run in normal mode and some - only with administrative rights.

Background

Usually the part of the program requires elevated privileges is a settings form which writes to Windows registry when the core functionality - don't.

Another case - a console application where core functionality requires elevated privileges and some helpers - such as help message displaying - don't.

The Code

Let's declare the skeleton of such console application.

Entry point method parses input command line arguments and branches the flow control relying on the parse results wrapped into an object:

C#
static void Main(string[] args)
{
    // wrap command line arguments to an object
    Core.Settings = ApplicationSettingsParser.Parse(args);
    if (Core.Settings.UsageFlag || (args.Length == 0))
    {
        // run without elevated privileges
        PrintUsage();
    }
    else if (!Core.Settings.EngageFlag)
    {
        // runs with the same arguments plus flag mentioning the main action performing
        var info = new ProcessStartInfo(
            Assembly.GetEntryAssembly().Location,
            String.Join(" ", Enumerable.Concat(args, new[] { "--engage" })))
        {
            Verb = "runas", // indicates to elevate privileges
        };

        var process = new Process
        {
            EnableRaisingEvents = true, // enable WaitForExit()
            StartInfo = info
        };

        process.Start();
        process.WaitForExit(); // sleep calling process thread until evoked process exit
    }
    else if (Core.Settings.EngageFlag)
    {
        // do stuff under elevated privileges
	Console.WriteLine("Elevated privileges gained={0}", Core.IsElevated);
    }
}

Here's a method just displaying a sample help message:

C#
private static void PrintUsage()
{
    Console.WriteLine("Usage: ElevatedPrivilegesOnDemand.exe --do [--engage] | -?");
}

Parsing method is placed into a dedicated helper:

C#
public static ApplicationSettings Parse(IEnumerable<string> args)
{
    var settings = new ApplicationSettings();
    foreach (var arg in args)
    {
        switch (arg)
        {
            case "-?":
            {
                // stop further parsing and return only meaning flag
                return new ApplicationSettings() { UsageFlag = true };
            }
            case "--do":
            {
                settings.DoFlag = true;
                break;
            }
            case "--engage":
            {
                settings.EngageFlag = true;
                break;
            }
        }
    }
    return settings;
}

Which returns a POCO object keeping settings:

C#
class ApplicationSettings
{
    public ApplicationSettings()
    {
        // default settings setup
    }

    public bool DoFlag { get; set; }

    public bool EngageFlag { get; set; }

    public bool UsageFlag { get; set; }
} 

Internal singleton setting instance is attached to a pivot class. It also contains an addition helper method to check elevated privileges obtaining:

C#
static class Core
{
	public static bool IsElevated
	{
		get
		{
			return new WindowsPrincipal
				(WindowsIdentity.GetCurrent()).IsInRole
				(WindowsBuiltInRole.Administrator);
		}
	}
	
	public static ApplicationSettings Settings { get; set; }
}

Details of Implementation

The executing flow is being separated to the two parts: in the first, it's being determined whenever elevated privileges are required relying on command line arguments specified or not. And if yes - an additional parameter is being added and passed to the same application but started with administrative rights and redirected console output.
And in the second, the core functionality is being executed with full privileges gained.

Summary

Now there is no needs to run the whole application under elevated privileges mode when it is not necessary.

Remark

Unfortunately, it seems that it's not possible to hide child process window and elevate its privileges in the same time:

  • 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

I'm investigating this behavior and will update my article as far will find a solution to hide a window of started elevated process.

Points of Interest

The reader can find the following links to be interesting:

Questions tagged UAC and manifest on Stack Overflow, especially this and related.

History

  • 28/08/2010 - Version 1.0.1 - Initial release
  • 29/08/2010 - Version 1.0.2 - Fix of example source code
  • 30/08/2010 - Version 1.1.3 - Code change and remark addition considering hiding window of process started with elevated privileges

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
.NET developer and architect

Comments and Discussions

 
QuestionElevation and shares Pin
francisco celedon15-Sep-22 11:45
francisco celedon15-Sep-22 11:45 
QuestionHow to use? Please Pin
Traibien27-Apr-17 22:48
Traibien27-Apr-17 22:48 
QuestionHiding the Child Process Window Pin
delftred6-Aug-15 19:40
professionaldelftred6-Aug-15 19:40 
GeneralMy vote of 5 Pin
williechen4-Feb-13 17:23
williechen4-Feb-13 17:23 
GeneralMy vote of 5 Pin
Justin Gross2-Nov-12 23:34
Justin Gross2-Nov-12 23:34 
GeneralRe: My vote of 5 Pin
Alexander Batishchev4-Nov-12 7:20
Alexander Batishchev4-Nov-12 7:20 
QuestionStarting up an app from Windows Service? Pin
miliu22-Mar-11 15:47
miliu22-Mar-11 15:47 
AnswerRe: Starting up an app from Windows Service? Pin
Alexander Batishchev23-Mar-11 0:35
Alexander Batishchev23-Mar-11 0:35 
GeneralRe: Starting up an app from Windows Service? Pin
miliu24-Mar-11 10:32
miliu24-Mar-11 10:32 
GeneralRe: Starting up an app from Windows Service? Pin
Alexander Batishchev25-Mar-11 1:36
Alexander Batishchev25-Mar-11 1:36 
GeneralRe: Starting up an app from Windows Service? Pin
miliu25-Mar-11 3:33
miliu25-Mar-11 3:33 
GeneralMy vote of 5 Pin
John Brett30-Aug-10 21:49
John Brett30-Aug-10 21:49 
Generalinteresting, but sample does not work out of the box Pin
ndinges29-Aug-10 0:53
ndinges29-Aug-10 0:53 
GeneralRe: interesting, but sample does not work out of the box Pin
Alexander Batishchev29-Aug-10 1:04
Alexander Batishchev29-Aug-10 1:04 
GeneralRe: interesting, but sample does not work out of the box Pin
Alexander Batishchev29-Aug-10 3:40
Alexander Batishchev29-Aug-10 3:40 
GeneralRe: interesting, but sample does not work out of the box Pin
ndinges29-Aug-10 5:00
ndinges29-Aug-10 5:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.