UAC对控制台应用程序的需求

28

我有一个控制台应用程序,需要使用一些需要管理员权限的代码。我阅读到需要添加一个类似以下内容的 Manifest 文件 myprogram.exe.manifest:

<?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>

但它仍然无法提升UAC(在控制台中或在VS中进行调试)。我该如何解决这个问题?

更新

如果我以管理员身份运行解决方案或以管理员身份运行/bin/*.exe,我就可以使其工作。我仍然想知道是否可能有一些东西会在应用程序启动时弹出,而不是明确右键单击>以管理员身份运行?


你是否以管理员身份运行应用程序? - Nick Berardi
我以普通用户身份运行VS,所以不行。但是当我右键单击控制台应用程序并以管理员身份运行时,它可以工作。我希望在Visual Studio中点击“运行”时出现“UAC弹窗”,而不是出现错误。 - Patrick Desjardins
顺便说一句,当我以管理员模式运行 VS 时,它可以工作。我想要的是,如果我没有以管理员身份运行,在弹出窗口中让我切换到管理员模式。 - Patrick Desjardins
你是否使用清单工具(mt.exe)将清单嵌入到myprogram.exe中?还是清单只是静静地存在于同一目录下的磁盘上? - bk1e
3个回答

55

如果你使用的是Visual Studio,那么这非常简单。在意识到它已经内置于VS之前,我将要去设置Windows SDK并进行mt.exe post-build步骤。我想我会记录下来以供后人参考。

  1. 项目|添加新项->Visual C# 项目->应用程序清单文件
  2. 打开app.manifest,更改requestedExecutionLevel.@level为“requireAdministrator”
  3. 生成


28

Scott的回答可以解决你的问题,但是微软建议控制台应用程序显示“访问被拒绝”的消息而不是提示提升权限。

http://msdn.microsoft.com/en-us/library/bb756922.aspx中得知:

控制台应用程序在控制台窗口上呈现其输出,而不是使用单独的用户界面。如果应用程序需要完整的管理员访问令牌来运行,则该应用程序需要从已提升的控制台窗口中启动。

对于控制台应用程序,您必须执行以下操作:

  1. 将应用程序标记为“asInvoker”:可以通过编写应用程序的清单来设置 RequestedExecutionLevel == asInvoker 来实现。这个设置允许来自非提升上下文的调用者创建您的进程,从而使他们可以继续执行步骤2。

  2. 如果应用程序在没有完整管理员访问令牌的情况下运行,请提供错误消息:如果在非提升的控制台中启动应用程序,则您的应用程序应给出简短的消息并退出。建议的消息是:“访问被拒绝。需要管理员权限才能使用所选选项。请使用管理员命令提示符完成这些任务。”

应用程序还应在无法启动时返回错误代码 ERROR_ELEVATION_REQUIRED,以便于脚本编写。

下面是我在 C# 中的代码,它已在 Windows XP(管理员-> 允许,标准用户-> 拒绝)和 Windows Server 2008(提升的管理员-> 允许,非提升的管理员-> 拒绝,标准用户-> 拒绝)上进行了测试。

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);
}

2
十几年后,这个指南仍然适用。在控制台应用程序中使用UAC的“requireAdministrator”的一个问题是,该应用程序将在单独的控制台中启动,并在退出时立即关闭。如果您的应用程序被提升到单独的控制台中,执行某些操作,打印一条消息,然后退出,用户将没有机会阅读消息,除非您在返回之前有一个愚蠢的“按任意键退出”暂停。 - Dave Ruske

9
你需要将UAC清单作为嵌入式Win32资源进行嵌入。请参见将UAC清单添加到托管代码

简而言之,您可以使用Windows SDK命令行工具将其嵌入到可执行文件中。

您可以在VS项目属性中将以下行作为后构建任务自动化此过程:

mt.exe -manifest "$(ProjectDir)$(TargetName).exe.manifest" -updateresource:"$(TargetDir)$(TargetName).exe;#1"

mt.exe在Windows SDK中吗?我访问了您的链接,但它似乎是C++。 - Patrick Desjardins
是的,它是Windows SDK的一部分。http://msdn.microsoft.com/en-us/library/aa375649(VS.85).aspx - Judah Gabriel Himango

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接