编写带有更新的Windows程序,权限问题

时间:2014-03-07 02:33:18

标签: c windows nsis uac

我想创建一个程序Foo.exe,错误登录到foo.log。该程序已安装(NSIS安装程序)到C:\Program Files (x86)\Foo\。在安装过程中,NSIS添加了一个快捷方式(CreateShortCut "$SMSTARTUP\Foo.lnk" "$INSTDIR\Foo.exe"),以便在Windows启动时启动Foo.exe

  • 当Windows在启动后执行我的程序时,它会使用"非管理权限启动我的程序。"。所以我的程序无法编辑C:\Program Files (x86)\Foo\foo.log。解决方法是将可编辑文件存储在另一个目录中,例如在$APPDATA
  • 但是这里出现了真正的问题:我在我的程序中添加了一个更新函数,它以下列方式工作:
    • 下载新二进制文件并保存为FooNew.exe。此文件没有任何权限(显式不是execute-flag)。
    • 使用执行权限创建自我复制:FooCopy.exe
    • 启动后,FooCopy.exe会打开FooNew.exe并将其内容写入Foo.exe。现在,Foo.exe已更新并具有执行权限。
    • FooCopy.exe将被删除。

所以我没有测试更新,但很可能它不会工作。我假设Foo.exe无法在C:\Program Files (x86)\Foo\中创建文件,因此更新在第1点失败。

一个想法是将Foo.exe保存在C:\Program Files (x86)\但不在$APPDATA中。所以该计划拥有所有必要的权利。问题是启动该程序:它是为32位编译的。是否有可能拥有一个发射器" C:\Program Files (x86)\Foo\launcher.exe启动$APPDATA中的实际应用程序?

这很困惑,不是吗?我怎么能改变自动更新程序,以便UAC不会踢我?

作为一个例子,我看到firefox.exe。因此,当正常没有人可以在不提示用户的情况下写入该目录时,如何更新,直接写入C:\Program Files (x86)\...

克里斯

2 个答案:

答案 0 :(得分:2)

Firefox使用NT服务。服务通常作为SYSTEM运行,因此它可以在任何地方复制文件,Mozilla可以配置他们的服务,以便普通用户可以启动

在程序文件和appdata中的主应用程序中使用启动程序是没有意义的,在这种情况下你也可以按用户安装(如Chrome等)。

我认为您的应用程序不是Web浏览器,因此保持最新状态可能并不重要。我建议您的更新程序只检查更新,如果有更新,您可以使用UAC以管理员身份再次生成自己(或主更新程序?),然后进行更新。

答案 1 :(得分:0)

您的“更新”流程需要使用管理权限运行。

如果启用了UAC,则可以通过将 runas 动词传递给ShellExecute来要求Windows启动更新程序:

Boolean RunAsAdmin(HWND hWnd, String filename, String, parameters)
{
    /*
       See Step 3: Redesign for UAC Compatibility (UAC)
       http://msdn.microsoft.com/en-us/library/bb756922.aspx
    */
    ShellExecuteInfo sei;

    ZeroMemory(ref sei, sizeoOf(sei));
    sei.cbSize = sizeof(TShellExecuteInfo);
    sei.Wnd = hwnd;
    sei.fMask = SEE_MASK_FLAG_DDEWAIT || SEE_MASK_FLAG_NO_UI;
    sei.lpVerb = "runas";
    sei.lpFile = Filename;
    if (parameters <> '')
        sei.lpParameters = parameters;
    sei.nShow = SW_SHOWNORMAL;

    return ShellExecuteEx(ref sei);
}

如果未启用UAC(例如,用户在Windows XP上运行),则用户将别无选择,只能以 具有管理权限的用户身份注销和登录。

  

注意:任何已发布到公共领域的代码。无需归属。