我正在尝试使用UrlDownloadToFile或InternetOpenUrl从DLL文件访问Internet上的某些链接。虽然它适用于.exe文件,但它不能从DLL文件中工作,甚至没有任何错误信息。它没有任何信息就失败了。
有人能给我任何帮助吗?提前谢谢。
我的代码如下:
extern "C" __declspec(dllexport) int __stdcall Hello()
{
HINTERNET hInt=NULL, hUrl=NULL;
hInt = InternetOpenA("Test Agent", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
hUrl = InternetOpenUrlA(hInt, "http://www.google.com.au", NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE, 0);
if (hUrl)
{
InternetCloseHandle(hUrl);
}
InternetCloseHandle(hInt);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Hello();
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
失败了:
hUrl = InternetOpenUrlA(hInt, "http://www.google.com.au", NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE, 0);
或者:
typedef HRESULT (__stdcall * lpURLDownloadToFile) (LPUNKNOWN pCaller, LPCTSTR szURL, LPCTSTR szFileName, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB);
extern "C" __declspec(dllexport) int __stdcall Hello()
{
HMODULE hModule = LoadLibraryW(L"urlmon.dll");
lpURLDownloadToFile urlD = (lpURLDownloadToFile)GetProcAddress( hModule, "URLDownloadToFileW" );
HRESULT aa = urlD(NULL, L"http://www.google.com.au", L"C:\\Test\\a.html", 0, NULL);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Hello();
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
失败了:
HRESULT aa = urlD(NULL, L"http://www.google.com.au", L"C:\\Test\\a.html", 0, NULL);
如果我在失败的上方插入一条像“MessageBox”这样的行,MessageBox将会成功显示。
如果我在失败之后插入像“MessageBox”这样的行,则不会显示MessageBox。如果我试图显示“hUrl”或“aa”,则不会返回任何错误代码。
答案 0 :(得分:1)
请勿在{{1}}中执行此操作。见DllMain entry point
入口点函数应该只执行简单的初始化或 终止任务。它不能调用LoadLibrary或LoadLibraryEx 函数(或调用这些函数的函数),因为这可能 在DLL加载顺序中创建依赖循环。这可能导致a 在系统执行其初始化代码之前使用DLL。
编辑,因为你想注入Dll并在其中运行代码。
单程使注入的Dll开始执行代码而不依赖于DllMain如下:
使用仅限一个帖子的消息钩子。
找到属于您要注入的进程的HWND。对于Internet Explorer,您可以使用EnumWindows枚举顶级Windows。主要IE Windows具有类DllMain
。使用EnumChildWindows查找班级IEframe
的窗口。使用GetWindowThreadProcessId获取关联的TID(线程标识符)。
使用SetWindowsHookEx安装线程挂钩。您可以选择Internet_Explorer Server
或WH_CALLWNDPROC
钩子。传递1中获得的TID。您的DLL被注入,并正在处理消息。
使用WH_GETMESSAGE
或PostMessage
或SendMessage
,具体取决于您在2中选择的挂钩类型,并注明消息。请参阅RegisterWindowMessage
在您的钩子函数中,过滤注册的消息(在DllMain中获取它的值并将其存储在全局变量中),当收到此消息时,请调用您的自定义代码。
警告:此技术非常适合短生活代码,您处于钩子函数中。这可能不是从互联网上下载的地方。
另一种方式是使用_ beginthreadex
在PostThreadMessage
中创建一个帖子
在该主题中,您可能拥有经典的RegisterClass / CreateWindow / GetMessage / DispatchMessage序列,并且您的EXE将能够向您的Dll发送/发送消息。
警告:根据您注入Dll的方式,您必须对过早卸载Dll非常感兴趣。如果线程仍然运行,则可能会发生崩溃。用这些东西保持清洁和稳定并不容易。但是,如果你只是在玩/试验,不要再费心而只是DllMain
(不是在DllMain中)你第二次拥有你的图书馆,它会永远留在这里。
你可以混合使用这两种技术,即:使用线程消息钩子来注入Dll并在钩子函数中启动一个线程。