33
\$\begingroup\$

I'm looking into Administration Elevation and I've come up with a solution that seems like it's perfectly sane, but I'm still in the dark about the professional methods to accomplish this.

Is there a better way to do this or is this fine?

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

namespace MyVendor.Installation
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            if (!IsRunAsAdmin())           
            {
                Elevate();
                Application.Exit();
            }
            else
            {
                try
                {
                    Installer InstallerForm = new Installer();
                    Application.Run(InstallerForm);
                }
                catch (Exception e)
                {
                    //Display Exception message!

                    Logging.Log.Error("Unrecoverable exception:", e);
                    Application.Exit();
                }
            }
        }

        internal static bool IsRunAsAdmin()
        {
            var Principle = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            return Principle.IsInRole(WindowsBuiltInRole.Administrator);
        }

        private static bool Elevate()
        {
            var SelfProc = new ProcessStartInfo
                {
                    UseShellExecute = true,
                    WorkingDirectory = Environment.CurrentDirectory,
                    FileName = Application.ExecutablePath,
                    Verb = "runas"
                };
            try
            {
                Process.Start(SelfProc);
                return true;
            }
            catch
            {
                Logging.Log.Error("Unable to elevate!");
                return false;
            }
        }
    }
}
\$\endgroup\$
22
\$\begingroup\$

You can create a manifest file and set the app to require administrative privileges. This will trigger the UAC user prompt with the dimmed screen when your application is run without requiring any code on your part.

See MSDN for the gory details:

This file can be created by using any text editor. The application manifest file should have the same name as the target executable file with a .manifest extension.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <assemblyIdentity version="1.0.0.0"
     processorArchitecture="X86"
     name="<your exec name minus extension>"
     type="win32"/> 
  <description>Description of your application</description> 
  <!-- Identify the application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
        </requestedPrivileges>
       </security>
  </trustInfo>
</assembly>
\$\endgroup\$
2
  • \$\begingroup\$ Would it be possible to elevate the application during runtime ? \$\endgroup\$
    – RobertPitt
    Jan 25 '11 at 19:25
  • \$\begingroup\$ @RobertPitt This way it will elevate on startup. It will not start unless admin rights are granted. \$\endgroup\$
    – Adam Lear
    Jan 25 '11 at 19:33
11
\$\begingroup\$

There are a couple of things that I would change in your code to make it clearer or mix well with standards.

    internal static bool IsRunAsAdmin()
    {
        var Principle = new WindowsPrincipal(WindowsIdentity.GetCurrent());
        return Principle.IsInRole(WindowsBuiltInRole.Administrator);
    }

I would change the name of this Method to RunningAsAdmin and the variable Principle should be lowercase to match the standard naming scheme for variables of camelCasing.

also I would change the structure of your if then statement in the Main Method.

instead of negating the boolean method I would let it play out, you are checking it one way or the other anyway so the negation just looks wrong

        if (RunningAsAdmin())           
        {
            try
            {
                Installer InstallerForm = new Installer();
                Application.Run(InstallerForm);
            }
            catch (Exception e)
            {
                //Display Exception message!

                Logging.Log.Error("Unrecoverable exception:", e);
                Application.Exit();
            }
        }
        else
        {
            Elevate();
            Application.Exit();
        }

Do we need Elevate to Return a boolean? from what I can see it doesn't really do anything with the true/false value.

Let's just make it a void method and let it do it's stuff and get outta there, no return statements.

    private static void Elevate()
    {
        var SelfProc = new ProcessStartInfo
            {
                UseShellExecute = true,
                WorkingDirectory = Environment.CurrentDirectory,
                FileName = Application.ExecutablePath,
                Verb = "runas"
            };
        try
        {
            Process.Start(SelfProc);
        }
        catch
        {
            Logging.Log.Error("Unable to elevate!");
        }
    }
\$\endgroup\$
4
\$\begingroup\$

Other options:

First: there is a mechanism to elevate "part" of an application via COM Monikers: run a part of the application out of process via COM, using a correctly formatted name to elevate (this is how Explorer elevates parts of itself). See MSDN http://msdn.microsoft.com/en-us/library/ms679687(v=vs.85).aspx

Second: as Anna says: use a manifest.

Third: run via runas as in the Q.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.