C++ 如何检测使用LoadLibraryEx加载的模块
我需要使用像或这样的windows函数来确定特定dll是否在代码执行的同一进程中加载 我正在寻找的一个模块是System.Windows.Forms.dll,但即使它是在进程中加载的。。。(在这里,您可以使用Process Explorer查看它) GetModuleHandle仍然找不到它C++ 如何检测使用LoadLibraryEx加载的模块,c++,.net,process,clr,C++,.net,Process,Clr,我需要使用像或这样的windows函数来确定特定dll是否在代码执行的同一进程中加载 我正在寻找的一个模块是System.Windows.Forms.dll,但即使它是在进程中加载的。。。(在这里,您可以使用Process Explorer查看它) GetModuleHandle仍然找不到它 HMODULE modHandle = GetModuleHandle(L"System.Windows.Forms.dll"); GetLastError()返回找不到的错误 如果函数成功,则
HMODULE modHandle = GetModuleHandle(L"System.Windows.Forms.dll");
GetLastError()返回找不到的错误
如果函数成功,则返回值是指定模块的句柄。
如果函数失败,则返回值为NULL
我认为这可能与CLR如何加载这些DLL有关。我注意到,如果使用LOAD_LIBRARY_AS_DATAFILE标志,则:
如果使用此值,系统将文件映射到调用
进程的虚拟地址空间,就好像它是一个数据文件一样。什么都不是
完成以执行或准备执行映射文件。所以你
无法调用诸如GetModuleFileName、GetModuleHandle或
使用此DLL的GetProcAddress
<> P>这也许是我的问题,但是不管原因是什么,有人知道在使用原生/C++代码的过程中找到一个被管理的dotnet DLL的方法吗?
谢谢
编辑:
根据Castorix在评论中的建议,我尝试使用EnumProcessModule:
HMODULE modules[100];
void* hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, GetCurrentProcessId());
if (hProcess)
{
DWORD bytesNeeded;
BOOL rc = EnumProcessModules(hProcess, modules, sizeof(modules), &bytesNeeded);
if (rc)
{
int count = (int)(bytesNeeded / sizeof(HMODULE));
for (int i = 0; i < count; i++)
{
wchar_t moduleName[260];
GetModuleFileName(modules[i], moduleName, 260);
}
}
}
CloseHandle(hProcess);
HMODULE模块[100];
void*hProcess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,0,GetCurrentProcessId());
if(hProcess)
{
德沃德·拜特斯曼;
BOOL rc=EnumProcessModules(需要hProcess、modules、sizeof(modules)和bytes);
if(rc)
{
int count=(int)(byteseeded/sizeof(HMODULE));
for(int i=0;i
这段代码找到了很多模块,但找不到System.Windows.Forms.dll
好的,这是一个试图回答的问题(或者说,对不起,这是一个太长的评论) 就我个人而言,我从未在Process Explorer窗格中见过托管的.NET DLL,但可能还不够仔细/经常查看。然而,我能(而且总是能)看到的是NGENed图像(
*.ni.dll
)
还请注意此处存在的System.Data.dll
,它不是NGENed,而是一个混合模式程序集,包含本机代码和托管代码
因此可以得出结论,您在这里只能看到NGENed和混合模式“程序集”,因为它们仍然由LoadLibrary
或LoadLibraryEx
加载
还要注意我的评论,我在这里复制了这些评论,以便于访问:
我认为CLR不使用LoadLibrary,这可以解释为什么
无法使用您描述的API“查看”它们。事实上
是一篇相关的博客文章。你可以随时查看来源
(CoreCLR,但不重要),特别是关于如何做。我
没有真正好的地方,但你可以开始
然后离开它。改用ICorDebug接口
以下是上面链接的博客条目中的一些相关引用:
你可能会问自己:……谁在乎?嗯,首先很好
知道。我还没有注意到上面的公共服务公告。
这是一个实现细节,但是CLR程序集不是偶数
保证使用文件实现,更不用说中的DLL文件了
使用LoadLibrary Win32 API加载的特定格式
然而,有几个工具和场景已经开始依赖
事实上,CLR使用LoadLibrary加载程序集。例如
直到CLR 4,如果您想知道加载了哪些.NET程序集
在您的过程中,一个相当可靠的启发式方法是启动
Sysinternals Process Explorer并查看给定进程的DLL视图
过程这不适用于CLR 4,您可以在此处看到:
坦白地说,我不知道Process Explorer如何在您的案例中显示程序集(不是NGENed模式,也不是混合模式),因为您正在观看CLR2进程。但是,请注意,PE不仅仅使用Win32 API。它还使用WMI,可能还直接使用CLR获取更多信息。例如,“Process Properties/.NET Assembly”和“Process Properties/.NET Performance”选项卡很可能分别使用ICorDebug
/ICorProfile
和性能计数器/ETW
您可能还需要在这些接口中的某个接口上使用,或者通常需要使用或中的其他一些接口
不管是什么,我不认为由于上述原因,
EnumProcessModules
等会让您到达那里。补充上述答案并提供相关代码;不可能使用像<代码>枚举进程模块< /C>的本机函数来检测非NoGeD的dotnet DLL,而我必须使用C++接口到CLR。< /P>
这里有更多信息:与此特定问题最相关的代码是:
HRESULT GetAssemblyFromAppDomain(_AppDomain* pAppDomain, LPCWSTR wszAssemblyName, _Deref_out_opt_ _Assembly **ppAssembly)
{
*ppAssembly = NULL;
// get the assemblies into a safearray
SAFEARRAY *pAssemblyArray = NULL;
HRESULT hr = pAppDomain->GetAssemblies(&pAssemblyArray);
if (FAILED(hr))
{
return hr;
}
// put the safearray into a smart ptr, so it gets released
CComSafeArray<IUnknown*> csaAssemblies;
csaAssemblies.Attach(pAssemblyArray);
size_t cchAssemblyName = wcslen(wszAssemblyName);
long cAssemblies = csaAssemblies.GetCount();
for (long i=0; i<cAssemblies; i++)
{
CComPtr<_Assembly> spAssembly;
spAssembly = csaAssemblies[i];
if (spAssembly == NULL)
continue;
CComBSTR cbstrAssemblyFullName;
hr = spAssembly->get_FullName(&cbstrAssemblyFullName);
if (FAILED(hr))
continue;
// is it the one we want?
if (cbstrAssemblyFullName != NULL &&
_wcsnicmp(cbstrAssemblyFullName,
wszAssemblyName,
cchAssemblyName) == 0)
{
*ppAssembly = spAssembly.Detach();
hr = S_OK;
break;
}
}
if (*ppAssembly == 0)
{
hr = E_FAIL;
}
return hr;
}
HRESULT GetAssemblyFromAppDomain(\u AppDomain*pAppDomain,LPCWSTR wszAssemblyName,\u Deref\u out\u opt\u Assembly**ppAssembly)
{
*ppAssembly=NULL;
//将程序集放入安全数组中
SAFEARRAY*pAssemblyArray=NULL;
HRESULT hr=pAppDomain->getAssemblys(&pAssemblyArray);
如果(失败(小时))
{
返回人力资源;
}
//将safearray放入智能ptr中,使其释放
CCOMSA射线CSA组件;
CSA附件(pAssemblyArray);
size_t cchAssemblyName=wcslen(wszAssemblyName);
long cAssemblies=csaAssemblies.GetCount();
用于(长i=0;iget_全名(&cbstrAssemblyFullName);
如果(失败(小时))
持续
//这是我们想要的吗?
如果(cbstrAssemblyFullName!=NULL&&
_wcsnicmp(cbstrAssemblyFullName,
wszAssemblyName,
cchAssemblyName)==0)