编写一个Windows程序更新,权限问题

我想创build一个程序Foo.exe并logging到foo.log 。 该程序已安装(NSIS安装程序)到C:\Program Files (x86)\Foo\ 。 在安装期间,NSIS在Windows启动时添加了一个快捷方式( CreateShortCut "$SMSTARTUP\Foo.lnk" "$INSTDIR\Foo.exe" )来启动Foo.exe

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

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

一个想法是将Foo.exe不保存在C:\Program Files (x86)\而是保存在$APPDATA 。 所以这个程序有所需要的权利。 问题是启动该程序:它被编译为32位。 有可能有一个“启动程序” C:\Program Files (x86)\Foo\launcher.exe启动$APPDATA的真实应用程序?

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

作为一个例子,我看到firefox.exe 。 它如何更新,从而直接写入C:\Program Files (x86)\...通常没有人可以写入该目录没有提示用户。

克里斯

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

在程序文件中有一个启动程序和appdata中的主要应用程序没有任何意义,您可能还需要按照每个用户的安装(如Chrome等)。

我假设你的应用程序不是一个网页浏览器,所以保持最新可能不是那么重要。 我建议你的更新只是检查更新,如果有更新,你可以重新生成自己(或主更新?)作为管理员使用UAC,然后进行更新。

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

如果启用了UAC,则可以让Windows通过将runas动词传递给ShellExecute来启动升级器:

 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上运行),则用户将别无选择,只能以具有管理权限的用户注销和登录。

注意 :任何代码发布到公共领域。 不需要归属