以前的做法是使用GetFileVersion()从文件中读取目标运行时版本。当可执行文件不包含CLR头时,它将失败并显示ERROR_BAD_FORMAT。适用于程序集的任何位数和任何目标架构。需要按照以下方式使用:
#define USE_DEPRECATED_CLR_API_WITHOUT_WARNING
#include <mscoree.h>
#pragma comment(lib, "mscoree.lib")
#include <assert.h>
bool IsExeFileDotNet(LPCWSTR filename)
{
WCHAR buf[16];
HRESULT hr = GetFileVersion(filename, buf, 16, NULL);
assert(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
return hr == S_OK;
}
请注意使用USE_DEPRECATED_CLR_API_WITHOUT_WARNING来抑制弃用错误,MSCorEE api在未来的.NET主要版本中可能会消失。
非过时的方法是使用ICLRMetaHost::GetFileVersion(),缺点是它只能在机器上安装了.NET 4时才能工作。这在今天并不是一个主要问题。看起来像这样:
#include <Windows.h>
#include <metahost.h>
#include <assert.h>
#pragma comment(lib, "mscoree.lib")
bool IsExeFileDotNet(LPCWSTR filename)
{
ICLRMetaHost* host;
HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (void**)&host);
assert(SUCCEEDED(hr));
if (hr == S_OK) {
WCHAR buf[16];
DWORD written;
hr = host->GetVersionFromFile(filename, buf, &written);
assert(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
host->Release();
}
return SUCCEEDED(hr);
}
其他直接搜索可执行文件中的CLR头文件的技术在这个问题和答案中提到。它们的可持续性很难预测。
/clr
编译的),但你的答案甚至可以更简单,直接查找导出函数_CorExeMain
。看起来 MS 头部的规范在这里;https://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx - Niall