如何从32位代码中启动64位Windows进程?

11

如果在Vista中写入HKLM注册表时需要弹出UAC对话框,我们选择不使用Win32 Registry API,因为当Vista权限不足时,我们需要以管理员权限重新启动整个应用程序。相反,我们使用以下技巧:

ShellExecute(hWnd, "runas" /* display UAC prompt on Vista */, windir + "\\Reg", "add HKLM\\Software\\Company\\KeyName /v valueName /t REG_MULTI_TZ /d ValueData", NULL, SW_HIDE);

这个解决方案很好,但是我们的应用程序是32位的,使用WOW兼容性层运行REG.EXE命令,就像它是一个32位应用程序一样!:( 如果从命令行运行REG.EXE,则会以64位模式正确运行。这很重要,因为如果作为32位应用程序运行,由于注册表反射,注册表键将会出错。

那么有没有办法从32位应用程序中以编程方式启动64位应用程序,并且不像其父32位进程一样使用WOW64子系统(即任务管理器中的“*”后缀)?

4个回答

14

尝试使用以下代码(来自32位进程):

> %WINDIR%\sysnative\reg.exe query ...

(在这里找到这里)。


如果这个有效,那听起来像是一个不错的技巧可以放在某人的工具包里。 - Jason R. Coombs
@DavidHeffernan:所以你捕获了错误并尝试使用System32再次尝试。 - Ben Voigt
1
@DavidHeffernan,有一个热补丁可以让sysnative在XP64上运行:32位应用程序无法访问运行64位版本的Windows Server 2003或Windows XP的计算机上的system32文件夹 - azhrei

9
无论是运行32位还是64位本地(非托管)程序,取决于可执行文件。在C:\ Windows \ System32(64位)和C:\ Windows \ SysWOW64(32位)中有两个reg.exe副本。因为您没有指定路径,所以您得到的是在PATH环境变量中首先出现的32位进程的32位版本。
您应该将此函数分解为单独的程序或COM对象,并使用清单标记该程序,或使用COM提升代号启动COM对象。

1
不要忘记,由于文件系统重定向(或者微软称之为其他什么),尝试打开/执行“c:\Windows\System32\foo.exe”的32位进程将会被静默重定向到“C:\windows\SysWow64\foo.exe”,除非采取具体措施禁用重定向。 - Michael Burr
是的,Mike,这就是我在将其标记为“答案”后注意到的。也就是说——实际上,在我的测试中,我确实已经写了完整的“System32”路径,所以它应该选择64位版本,但实际上没有。我认为这是你指出的原因。 :) - Jonas
“PATH 中出现的任何内容都是优先考虑”的注释并不完全正确。无论是 32 位还是 64 位,PATH 都会指向 system32。当从 32 位进程调用 ShellExecute 时,会发生文件系统重定向到 syswow64。你不能交换系统目录在 PATH 变量中出现的顺序并改变其行为! - David Heffernan
我认为这个答案不起作用,就像Michael所说的那样。@Jonas,你可以再次点击复选框来“取消接受”它。 - rogerdpack

2

你有没有考虑创建一个小的“助手”应用程序来为你更新注册表?如果你将其编译为64位并包含一个指示需要管理员权限的清单,那么它将为你覆盖两个方面。

有API可以检测你运行的操作系统的“位数”,因此你可以编译RegistryUpdate32.exe和RegistryUpdate64.exe并调用相关的一个。


1

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