我发现,当从托管代码调用 GetBinaryType 时,我得到的结果与从同一台机器上的 native 代码调用 GetBinaryType 的结果相反。
我从别处借用了编码声明:
public enum BinaryType : uint
{
SCS_32BIT_BINARY = 0, // A 32-bit Windows-based application
SCS_64BIT_BINARY = 6, // A 64-bit Windows-based application.
SCS_DOS_BINARY = 1, // An MS-DOS – based application
SCS_OS216_BINARY = 5, // A 16-bit OS/2-based application
SCS_PIF_BINARY = 3, // A PIF file that executes an MS-DOS – based application
SCS_POSIX_BINARY = 4, // A POSIX – based application
SCS_WOW_BINARY = 2 // A 16-bit Windows-based application
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetBinaryType(
string lpApplicationName,
out BinaryType dwBinType
);
然后将函数调用为
bool is64bit = false;
BinaryType binType = BinaryType.SCS_32BIT_BINARY;
// Figure out if it's 32-bit or 64-bit binary
if (GetBinaryType(phpPath, out binType) &&
binType == BinaryType.SCS_64BIT_BINARY)
{
is64bit = true;
}
对于 32 位 native 二进制文件,GetBinaryType 返回 BinaryType.SCS_64BIT_BINARY (6),对于 64 位 native 二进制文件,返回 BinaryType.SCS_32BIT_BINARY (0)。
为了验证,我编写了一个 native 命令行工具,并针对相同的二进制文件运行它。
PCWSTR rgBinTypes[] = {
L"SCS_32BIT_BINARY", // 0
L"SCS_DOS_BINARY", // 1
L"SCS_WOW_BINARY", // 2
L"SCS_PIF_BINARY", // 3
L"SCS_POSIX_BINARY", // 4
L"SCS_OS216_BINARY", // 5
L"SCS_64BIT_BINARY", // 6
};
int _tmain(int argc, _TCHAR* argv[])
{
DWORD binType;
if (argc < 2)
{
wprintf(L"Usage: %S <binary-path>\n", argv[0]);
goto Cleanup;
}
if (!GetBinaryType(argv[1], &binType))
{
wprintf(L"Error: GetBinaryType failed: %d\n", GetLastError());
goto Cleanup;
}
wprintf(L"Binary type: %d (%s)\n", binType, binType < 7 ? rgBinTypes[binType] : L"<unknown>");
Cleanup:
return 0;
}
命令行工具为 32 位 native 二进制文件正确返回 0 (SCS_32BIT_BINARY),为 64 位 native 二进制文件正确返回 6 (SCS_64BIT_BINARY)。
我发现有人提到了同样的问题,但没有提供答案:https://social.msdn.microsoft.com/Forums/en-US/fc4c1cb4-399a-4636-b3c3-a3b48f0415f8/strange-behavior-of-getbinarytype-in-64bit-windows-server-2008?forum=netfx64bit
还有其他人遇到过这个问题吗?
我意识到我可以在我的托管枚举中翻转定义,但这看起来非常笨拙。
最佳答案
这是 WinAPI 错误/开发人员的疏忽。 You may find this related question useful to read , 和 it's top answer may help you find the appropriate workaround ,
Use a separate 64 bit process, and some IPC, to retrieve the information.
Use WMI to get the module file name.
Use
QueryFullProcessImageName
.
我最终采用了完全不同的解决方法。 This answer关于 PE 头文件提到了 32 位和 64 位 Windows 可执行文件中的 PE 头文件。您可以完全绕过 WinAPI 检查,并通过以二进制模式读取目标可执行文件并检查它是否与 PE 签名匹配来检查您的目标可执行文件。
遗憾的是,网上没有太多关于该问题的信息。我记得在某个论坛上看到过这个问题,它被明确列为错误,但这是大约 10 年前的事了。我希望在我们讨论这个问题时,更多的人会意识到这一点。
关于c# - 托管代码中的 GetBinaryType 给出相反的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36486618/