您几乎肯定会遇到 Windows Installer Detection Technology? 兼容性启发式。
Windows 将尝试检测应用程序何时是安装程序,并且可能需要提升。
安装程序检测仅适用于:
- 32 位可执行文件
- 没有
requestedExecutionLevel 的应用程序
- 以标准用户身份运行并启用 LUA 的交互式进程
在创建32位进程之前,会检查以下属性以确定它是否是安装程序:
- 文件名包含“安装”、“设置”、“更新”等关键字。
- 以下版本控制资源字段中的关键字:供应商、公司名称、产品名称、文件描述、原始文件名、内部名称和导出名称。
- 嵌入在可执行文件中的并行清单中的关键字。
- 可执行文件中链接的特定 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="ITReasearchAssociates.Contoso.Updater"
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()
{
//Public domain: no attribution required
//A user can be a member of the Administrator group, and yet not be an administrator.
//Conversely, the user can be an administrator while not being 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)
{
//Public domain: no attribution required
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);
}
}
注意:任何代码都会发布到公共领域。无需署名。