views:

1077

answers:

3

I have a console application that require to use some code that need administrator level. I have read that I need to add a Manifest file myprogram.exe.manifest that look like that :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator">
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

But it still doesn't raise the UAC (in the console or in debugging in VS). How can I solve this issue?

Update

I am able to make it work if I run the solution in Administrator or when I run the /bin/*.exe in Administrator. I am still wondering if it's possible to have something that will pop when the application start instead of explicitly right click>Run as Administrator?

+3  A: 

You need to embed the UAC manifest as an embedded Win32 resource. See Adding a UAC Manifest to Managed Code.

In short, you use a Windows SDK command line tool to embed it into your executable.

You can automate this as a post-build step by placing the following line as a post build task in your VS project's properties:

mt.exe -manifest "$(ProjectDir)$(TargetName).exe.manifest" -updateresource:"$(TargetDir)$(TargetName).exe;#1"
Judah Himango
mt.exe is in the Windows SDK? I have visited your link but it's look to be C++.
Daok
It's part of the Windows SDK, yes. http://msdn.microsoft.com/en-us/library/aa375649(VS.85).aspx
Judah Himango
+4  A: 

For anyone using Visual Studio, it's super easy. I was about to go set up the Windows SDK and do mt.exe post-build steps and all that before realizing it's built into VS. I figured I'd record it for posterity.

  1. Project | Add New Item -> Visual C# Items -> Application Manifest File
  2. Open app.manifest, change requestedExecutionLevel.@level to "requireAdministrator"
  3. Build

Ta-da

Scott Bilas
+1  A: 

Scott's answer will do what you asked, but Microsoft recommends that console applications display an "access denied" message rather than prompt for elevation.

From http://msdn.microsoft.com/en-us/library/bb756922.aspx:

A console application presents its output on the console window and not with a separate user interface. If an application needs a full administrator access token to run, then that application needs to be launched from an elevated console window.

You must do the following for console applications:

  1. Mark that your application “asInvoker”: You can do this by authoring the manifest of your application in which you set RequestedExecutionLevel == asInvoker. This setup allows callers from non-elevated contexts to create your process, which allows them to proceed to step 2.

  2. Provide an error message if application is run without a full administrator access token: If the application is launched in a non-elevated console, your application should give a brief message and exit. The recommended message is: "Access Denied. Administrator permissions are needed to use the selected options. Use an administrator command prompt to complete these tasks."

The application should also return the error code ERROR_ELEVATION_REQUIRED upon failure to launch to facilitate scripting.

My C# code for this is below. It is tested on Windows XP (administrator -> ok, standard user -> denied) and Windows Server 2008 (elevated administrator -> ok, non-elevated administrator -> denied, standard user -> denied).

static int Main(string[] args)
{
    if (!HasAdministratorPrivileges())
    {
        Console.Error.WriteLine("Access Denied. Administrator permissions are " +
            "needed to use the selected options. Use an administrator command " +
            "prompt to complete these tasks.");
        return 740; // ERROR_ELEVATION_REQUIRED
    }

    ...
    return 0;
}

private static bool HasAdministratorPrivileges()
{
    WindowsIdentity id = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(id);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
Joe Daley