如何查明exe文件是.Net exe还是常规exe
How to find out if a exe file is a .Net exe or regular exe?
这不是下面SO问题的重复:如何判断win32应用程序是否使用.NET运行时。
如果给定的exe文件是.net exe文件还是常规的WIN32/WIN64 exe文件,我如何通过程序查找?
这个问题不是关于询问一个正在运行的进程,而是关于一个exe文件,正如标签所示,不需要用VB.net或C#编写的解决方案。
我需要一个带有签名的函数,例如:
// return true if filename is a exe file for .Net
bool IsExeFileDotNet(LPCTSTR filename)
{
...
}
旧的备用是使用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_WWARNING来抑制弃用错误,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);
}
本Q+A中提到了直接插入可执行文件以在文件中查找CLR头的其他技术。很难猜测它们未来会如何证明。
一种方法是询问PE标头等以获取正确的标志。有几个链接可供进一步阅读;这里和这里(以及MSDN的一篇旧文章)。
PE标头上的MS文档可用(带有许可协议)。
最简单的方法可能只是列出依赖的dll(因为这只适用于主exe)并查找mscoree.dll的存在。导入表将包括mscoree.dll以及函数_CorExeMain
的include和entry(来自mscoree..dll)。有关这方面的更多链接可以在SO和GitHub上找到,这似乎是一个广泛的示例,以及本文(关于CodeGuru),其中包含您所需的签名为BOOL IsManaged(LPTSTR lpszImageName)
的函数的代码(许可证似乎限制了重新发布)。
这个想法是检查是否存在特殊的PE目录IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
。
我最近写了类似的函数,这里是代码,你可以使用它。事实上,我已经为句柄使用了智能包装器,但这里省略了它,所以添加了CloseHandle的expicit调用。此外,在ReadFile/SetFilePointer调用后检查错误也是一个好主意。无论如何,我希望它能有用:
BOOL IsDotNetApp(LPCWSTR szPath)
{
HANDLE hFile = CreateFileW(szPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hFile)
return FALSE;
DWORD temp;
IMAGE_DOS_HEADER IMAGE_DOS_HEADER_;
ReadFile(hFile, &IMAGE_DOS_HEADER_, sizeof(IMAGE_DOS_HEADER_), &temp, NULL);
SetFilePointer(hFile, IMAGE_DOS_HEADER_.e_lfanew, NULL, FILE_BEGIN);
const int nNtHeaderMaxSize = sizeof(IMAGE_NT_HEADERS64);
BYTE NT_HEADERS[nNtHeaderMaxSize];
ReadFile(hFile, NT_HEADERS, nNtHeaderMaxSize, &temp, NULL);
PIMAGE_NT_HEADERS pNT_HEADERS = (PIMAGE_NT_HEADERS)NT_HEADERS;
BOOL bRes;
if (pNT_HEADERS->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
{
bRes = 0 != ((PIMAGE_NT_HEADERS32)NT_HEADERS)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
}
else if (pNT_HEADERS->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
bRes = 0 != ((PIMAGE_NT_HEADERS64)NT_HEADERS)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
}
else
{
// Unknown header type
bRes = FALSE;
}
CloseHandle(hFile);
return bRes;
}
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 终端不会为C++文件创建.exe文件吗
- 在Windows中以.exe的形式运行c++
- Visual Studio mkl_link_tool.exe链接错误
- PrintWindow函数在notepad.exe中出错
- 在 C++/CLI 中将 .NET 事件从一个 DLL 引发到另一个 DLL
- 如何在 64 位 vb.net Windows 应用程序中引用 32 位 dll
- VSCode C++ 编译的exe感染了Win32:TrojanX-gen[Trj]
- 将返回值从 exe 传递到 bat,并将其传递给 C# 中的进程
- 获取当前正在运行的 exe 名称(不是路径)
- 加载与引用 .NET DLL 位于同一文件夹中的引用的 .NET DLL 时"Not found"异常
- 从 exe 文件 (Visual Studio ) 启动时调试断言失败
- 1d.exe找不到SFML文件?
- 在没有.NET框架的情况下运行.NET EXE应用程序
- C++ dll variable to vb.net exe
- 将 .NET C# 程序集成到已编译(非托管)C++程序中(无需执行单独的.exe文件)
- 获取传递给子模块(C#.NET dll)中的主模块(VC++ exe)的参数
- 如何查明exe文件是.Net exe还是常规exe
- 如何从C++程序(.NET 4)运行regasm.exe
- 用VB重写的c++ out-proc COM服务器.. NET和跨c++ EXE共享