2013-11-20 30 views
15

在我的VB6应用程序中,我打开其他EXE文件。我的应用程序在没有任何UAC提示的情况下运行,但是我有一个检查软件更新的EXE。这会提示UAC提示。那么Windows如何决定是否显示UAC提示?我看到这个link。那么它取决于我在我的应用程序中编写的代码?有趣的是,我的应用程序(这是主EXE文件)不会提示UAC,而检查和下载更新的小EXE会提示UAC。我拥有数字签名的所有EXE文件。我已经在以下链接一览:Windows如何决定是否显示UAC提示?

http://msdn.microsoft.com/en-us/library/windows/desktop/aa511445.aspx

http://technet.microsoft.com/en-us/library/cc505883.aspx和其他一些。

但是我仍然不清楚它。

回答

19

您几乎肯定会遇到Windows Installer Detection Technology兼容性启发式问题。 Windows将尝试检测应用程序是安装程序的时间,并且可能需要升级。

安装程序检测仅适用于:

  1. 32位可执行文件
  2. 应用程序不运行与LUA标准用户启用

32前requestedExecutionLevel

  • 互动过程bit进程被创建,检查以下属性以确定它是否是安装程序:

    • 文件名包括像关键字“安装”,“设置”,“更新”等
    • 关键词在以下版本资源领域:供应商,公司名称,产品名称,文件描述,原始文件名,内部名称和导出名称。
    • 嵌入在可执行文件中的并排清单中的关键字。
    • 可执行文件中链接的特定StringTable条目中的关键字。
    • 可执行文件中链接的RC数据中的关键属性。
    • 可执行文件中字节的目标序列。
  • 因此,当你说:

    ,但我有一个exe,检查软件更新

    我的猜测是,这是CheckForUpdates.exe触发兼容性启发。

    正确的事情是一个集清单到你的“检查”的可执行文件,通知的Windows,它应该提升工具。这与asInvoker一个requestedExecutionLevel在清单中完成:

    AssemblyManifest.xml:

    <?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="client" 
         type="win32" 
        /> 
    
        <description>Update checker</description> 
    
        <!-- Run as standard user. Disable file and registry virtualization --> 
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> 
         <security> 
         <requestedPrivileges> 
          <requestedExecutionLevel level="asInvoker" uiAccess="false"/> 
         </requestedPrivileges> 
         </security> 
        </trustInfo> 
    </assembly> 
    

    这样,你“检查更新”应用程序将永远不会提升,从不​​误获得管理权限。

    如果您希望您的更新程序实际上是应用更新(需要管理权限的更新),那么您将以管理员身份启动更新程序应用程序。

    示例代码

    //Check if there are updates available 
    if (!CheckForUpdatesAvailable()) 
        return; //no updates. We're done 
    
    //If the user is an administrator, then get the update 
    if (IsUserAnAdmin()) 
    { 
        //Maybe throw in a "Hey, user, wanna get the update now?" dialog 
        DownloadAndApplyUpdates(); 
        return; 
    } 
    
    //The user is not an admin. 
    //Relaunch ourselves as administrator so we can download the update 
    //Maybe throw in a "Hey, user, wanna get the update now?" dialog. A button with a UAC shield on it 
    ExecuteAsAdmin(Application.ExecutablePath, "/downloadUpdate"); 
    

    与辅助功能:

    private Boolean IsUserAnAdmin() 
    { 
        //A user can be a member of the Administrator group, but not an administrator. 
        //Conversely, the user can be an administrator and not a member of the administrators group. 
        var identity = WindowsIdentity.GetCurrent(); 
        return (null != identity && new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator)); 
    } 
    
    private void ExecuteAsAdmin(string Filename, string Arguments) 
    { 
        ProcessStartInfo startInfo = new ProcessStartInfo(Filename, Arguments); 
        startInfo.Verb = "runas"; 
        System.Diagnostics.Process.Start(startInfo); 
    } 
    

    然后你只需要在启动时查找的/downloadUpdate命令行参数来知道你工作实际上是做工作的:

    public Form1() 
    { 
        InitializeComponent(); 
    
        //Ideally this would be in program.cs, before the call to Application.Run() 
        //But that would require me to refactor code out of the Form file, which is overkill for a demo 
        if (FindCmdLineSwitch("downloadUpdate", true)) 
        { 
         DownloadAndApplyUpdates(); 
         Environment.Exit(0); 
        } 
    } 
    

    注意:任何代码被释放到公共领域。无需归属。

    +0

    我会补充说上面列出的文件名规则几乎肯定是不完整的。我有一个应用程序,当它命名为APP123.exe时,需要UAC,如果重命名为APP.exe,则不需要UAC。 – DaveInCaz

    1

    有人可以在exe的配置中指定该文件需要用更高的权限执行。

    How to request Admin Privileges

    我不知道这个更新是的,但我认为它需要更新像一个服务,或者位于PROGRAMFILES-DIR一些文件的组成部分。因此它需要管理权限。

    +0

    我怀疑Windows是如何决定uac应该提示还是不提示。您的方法以管理员身份运行该程序,并要求用户输入管理员的密码。 –

    +0

    尽管Codeproject文章并不完整,但它仍然是如何工作的。您可以选择不同的选项,您可以在该清单中寻求具有微妙或不存在差异的选项(例如请求最高可能的特权或管理特权或等等),但基本上就是这样。 Windows的安全性非常愚蠢,但另一方面,我希望我可以引用一个不笨的系统(Linux甚至更愚蠢,因为它可以让你键入root密码......)。 – Damon

    0

    当需要特权提升时,使用UAC提示。您自己的VB6应用程序不需要它,因此默认行为是OK。更新程序需要该权限,因此其作者将可执行程序标记为需要它。 Windows发现并提出了UAC提示。

    现在,根据确切的Windows版本和安全更新,该权限可以保留一段时间,甚至是其他(子)进程。这可能会阻止重复的UAC提示。

    +0

    更新器由我创建。那么一些代码会触发UAC提示?我没有在我的代码中以admin身份运行updater exe(以admin身份运行,导致UAC始终提示)。那么是否有一些代码触发了UAC? –

    +1

    我相信Windows确实有一些额外的启发法:比如过去是否需要UAC?它是否被命名为“setup.exe”? – MSalters

    +0

    文件名不是setup.exe。但UAC是否也依赖于文件名? –

    1

    您的程序可能缺少将其标记为非遗留的应用程序清单。因此,Windows将应用脚本安装程序检测启发式来确定您的程序是否为安装程序。这几乎是提出“意外”UAC提示的唯一方式。

    这些启发法包括EXE文件名中的关键字搜索以及EXE的几个扩展属性,甚至可能会在文件内查找众所周知的二进制签名(即字节字符串)。

    顺便说一句,你的加密签名根本就没有进入。如果它不是由可信任的CA颁发,它不会有帮助。

    对于这个问题,只要因为Windows在UAC提示符上报告公共名称而信任代码的人就是一个傻瓜。恶意软件作者一直在窃取这些内容,因此,当垃圾程序导致问题时,他们很容易获取并且几乎从未由用户报告过。节省你的钱,代码签名证书是一个失败的概念。

    +0

    好的。所以如果没有以管理员身份运行并且拥有适当的清单文件,可以避免UAC提示符在我的情况下? –

    +0

    另外如何创建一个清单文件,它将使应用程序在没有UAC提示的情况下启动? –

    +1

    @ITresearcher:如果这是你真正的问题(如何防止提示),你应该问 - 并提供比这个问题更多的信息。但答案很可能是:“UAC提示有很好的理由,你正在改变安装的软件,这应该是用户的有意决定。” – MSalters