从* nix世界来的时候,我对Windows的行为以及它的安全系统非常困惑。
我只是想在我的应用程序中执行外部程序。我发现WinAPI函数ShellExecute按预期工作,除非在%windir%\ System32 子目录中启动某些程序。
执行ping.exe成功
ShellExecute(NULL, "open", "c:\\Windows\\System32\\ping.exe', NULL, NULL, SW_SHOW) );
// ^^^ OK, retcode == 42
执行java.exe失败
ShellExecute(NULL, "open", "c:\\Windows\\System32\\java.exe', NULL, NULL, SW_SHOW) );
// ^^^ ERROR_FILE_NOT_FOUND, retcode == 2
这很奇怪,因为 java.exe确实存在于System32 中,具有对用户组的读取/执行权限,可以从cmd调用。
C:\>dir /q c:\Windows\System32\java.exe
Volume in drive C has no label.
Volume Serial Number is 56E3-0868
Directory of c:\Windows\System32
11.01.2012 23:40 172 320 NT AUTHORITY\SYSTEM java.exe
1 File(s) 172 320 bytes
0 Dir(s) 226 127 564 800 bytes free
C:\>cacls c:\Windows\System32\java.exe
c:\Windows\System32\java.exe NT AUTHORITY\SYSTEM:F
BUILTIN\Administrators:F
BUILTIN\Users:R
我在这里缺少什么?
操作系统是Windows 7家庭版。
更新:如果我将c:\ Windows \ Sytem32 \ calc.exe复制到c:\ Windows \ Sytem32 \ calc2.exe, ShellExecute可以运行原始calc.exe但是会失败calc2.exe虽然文件相同!! 唯一的区别是TrustedInstaller组的附加权限,其中缺少calc2.exe和java.exe。巧合?
答案 0 :(得分:10)
您运行的是64位操作系统吗?
如果是这样,C:\Windows\System32
将包含64位二进制文件,而C:\Windows\SysWOW64
将包含32位二进制文件(是的,它实际上就是这样)。出于向后兼容性原因,在运行32位进程时,Windows会将C:\Windows\System32
的访问权限重定向到C:\Windows\SysWOW64
。
因此,如果您使用32位进程查看C:\Windows\System32
,您实际上会看到C:\Windows\SysWOW64
中的内容。
您可以调用Wow64DisableWow64FsRedirection
函数来禁用此行为。请注意文档中的警告,并仔细考虑它是否适用于您的情况:
注意:
Wow64DisableWow64FsRedirection
函数会影响当前线程执行的所有文件操作,如果在任何时间长度内禁用文件系统重定向,则可能会产生意外后果。例如,DLL加载取决于文件系统重定向,因此禁用文件系统重定向将导致DLL加载失败。此外,许多功能实现使用延迟加载,并且在禁用重定向时将失败。初始延迟加载操作的失败状态是持久的,因此即使在重新启用文件系统重定向之后,延迟加载功能的任何后续使用也将失败。要避免这些问题,请在调用不能重定向的特定文件I / O函数(例如CreateFile
)之前立即禁用文件系统重定向,然后使用Wow64RevertWow64FsRedirection
立即重新启用文件系统重定向。
答案 1 :(得分:1)
使用ProcessMonitor确定正在访问哪些文件以及哪些文件操作失败以及原因。
答案 2 :(得分:0)
检查环境设置,例如“路径”。 Windows为系统和用户保留了单独的环境。可能是Java.exe所需的DLL仅在一个环境中列出,当您通过ShellExecute运行它时,它正在使用其他环境。