The problem and the answer to this question that you are talking about concern the processing of window messages in a stream with your activity, the so-called "message pump". You do:
Sleep(20000);
And that is the cause of the problem. Instead, you should wait. And you should process window messages while waiting. Instead, it should be a loop with these dispatch messages:
MSG Message; while(PeekMessage(&Message, NULL, WM_NULL, WM_NULL, PM_REMOVE)) { TranslateMessage(&Message); DispatchMessage(&Message); }
In this way, messages in a window that IE or COM could send as part of processing your request have reached the target windows and will be processed. Instead, you block the thread, giving it the ability to not do what it should do. However, the loop above only sends messages once, so if you need a timeout, you can do it like an endless loop waking up with some sign of success or processing failure, or a loop based on an event that wakes up the message and goes back to sleep. without losing processor cycles.
That is, your Sleep was still processing window messages for 20 seconds, it may have been like this (the fragment should be good for copy / paste to replace):
const ULONG nTimeoutTime = GetTickCount() + 20 * 1000; // In 20 seconds const HANDLE hFakeEvent = CreateEvent(NULL, TRUE, FALSE, NULL); for(; ; ) { const LONG nWaitTime = nTimeoutTime - GetTickCount(); if(nWaitTime <= 0) break; // Timeout const DWORD nWaitResult = MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, nWaitTime, QS_ALLINPUT | QS_ALLPOSTMESSAGE); //ATLTRACE(_T("nWaitResult 0x%x\n"), nWaitResult); //ATLASSERT(nWaitResult == WAIT_OBJECT_0 + 1 || nWaitResult == WAIT_TIMEOUT); if(nWaitResult == WAIT_TIMEOUT) break; // Timeout MSG Message; while(PeekMessage(&Message, NULL, WM_NULL, WM_NULL, PM_REMOVE)) { //ATLTRACE(_T("Message.hwnd 0x%p, Message.message 0x%04x\n"), Message.hwnd, Message.message); TranslateMessage(&Message); DispatchMessage(&Message); } } CloseHandle(hFakeEvent);