urldownloadtofile或InternetOpenUrl无法从DLL工作

时间:2013-12-30 12:12:20

标签: api dll c++11

我正在尝试使用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”,则不会返回任何错误代码。

1 个答案:

答案 0 :(得分:1)

请勿在{{1​​}}中执行此操作。见DllMain entry point

  

入口点函数应该只执行简单的初始化或   终止任务。它不能调用LoadLibrary或LoadLibraryEx   函数(或调用这些函数的函数),因为这可能   在DLL加载顺序中创建依赖循环。这可能导致a   在系统执行其初始化代码之前使用DLL。

编辑,因为你想注入Dll并在其中运行代码。

单程使注入的Dll开始执行代码而不依赖于DllMain如下:

使用仅限一个帖子的消息钩子。

  1. 找到属于您要注入的进程的HWND。对于Internet Explorer,您可以使用EnumWindows枚举顶级Windows。主要IE Windows具有类DllMain。使用EnumChildWindows查找班级IEframe的窗口。使用GetWindowThreadProcessId获取关联的TID(线程标识符)。

  2. 使用SetWindowsHookEx安装线程挂钩。您可以选择Internet_Explorer ServerWH_CALLWNDPROC钩子。传递1中获得的TID。您的DLL被注入,并正在处理消息。

  3. 使用WH_GETMESSAGEPostMessageSendMessage,具体取决于您在2中选择的挂钩类型,并注明消息。请参阅RegisterWindowMessage

  4. 在您的钩子函数中,过滤注册的消息(在DllMain中获取它的值并将其存储在全局变量中),当收到此消息时,请调用您的自定义代码。

  5. 警告:此技术非常适合短生活代码,您处于钩子函数中。这可能不是从互联网上下载的地方。

    另一种方式是使用_ beginthreadex

    PostThreadMessage中创建一个帖子

    在该主题中,您可能拥有经典的RegisterClass / CreateWindow / GetMessage / DispatchMessage序列,并且您的EXE将能够向您的Dll发送/发送消息。

    警告:根据您注入Dll的方式,您必须对过早卸载Dll非常感兴趣。如果线程仍然运行,则可能会发生崩溃。用这些东西保持清洁和稳定并不容易。但是,如果你只是在玩/试验,不要再费心而只是DllMain(不是在DllMain中)你第二次拥有你的图书馆,它会永远留在这里。

    你可以混合使用这两种技术,即:使用线程消息钩子来注入Dll并在钩子函数中启动一个线程。