2010-10-12 1 views
0

Я разместил этот вопрос на форумах MSDN, но мой опыт был лучшим качеством ответа здесь, в Stack Overflow, поэтому я также размещаю здесь. Как я уже писал несколько раз раньше, я работаю над каркасом автоматизации браузера, автоматизируя Internet Explorer из внешнего процесса. Моя архитектура выглядит следующим образом: у меня есть сервер, который открывает именованный канал, который мой клиент автоматизации нажимает на команды. Сервер интерпретирует команды и выполняет их на объекте IWebBrowser2, который я завернул в свой собственный класс C++. Все работает нормально, пока я не попытаюсь потопить события в IE-экземпляре. Мой класс-оболочка реализует IDispEventSimpleImpl, но когда я пытаюсь потопить события, экземпляр браузера не отвечает ни на какое общение, ни программно, ни через пользовательский интерфейс. Вот мои основные два метода с наиболее актуальными:Понижение событий DWebBrowserEvents2, похоже, повредит программную навигацию

void BrowserManager::Start(void) 
{ 
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
    std::basic_string<TCHAR> pipeName =L"\\\\.\\pipe\\managerpipe"; 
    HANDLE hPipe = ::CreateNamedPipe(pipeName.c_str(), 
    PIPE_ACCESS_DUPLEX, 
    PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 
    PIPE_UNLIMITED_INSTANCES, 
    1024, 
    1024, 
    0, 
    NULL); 

    if (hPipe == INVALID_HANDLE_VALUE) 
    { 
    DWORD dwError = ::GetLastError(); 
    } 

    this->m_isRunning = true; 

    while (this->m_isRunning) 
    { 
    BOOL result = ::ConnectNamedPipe(hPipe, NULL); 
    std::vector<CHAR> inputBuffer(1024); 
    DWORD bytesRead = 0; 
    ::ReadFile(hPipe, &inputBuffer[0], 1024, &bytesRead, NULL); 

    std::string command = &inputBuffer[0]; 
    std::string response = DispatchCommand(command); 

    std::vector<CHAR> outputBuffer(response.begin(), response.end()); 
    ::WriteFile(hPipe, &outputBuffer[0], outputBuffer.size(), &bytesRead, NULL); 
    ::FlushFileBuffers(hPipe); 
    ::DisconnectNamedPipe(hPipe); 

    if (strcmp(command.c_str(), "quit\r\n") == 0) 
    { 
     this->m_isRunning = false; 
    } 
    } 

    ::CloseHandle(hPipe); 
    CoUninitialize(); 
} 

std::string BrowserManager::DispatchCommand(std::string command) 
{ 
    std::string response; 
    if (strcmp(command.c_str(), "start\r\n") == 0) 
    { 
    // Launch the browser process using CreateProcess on XP 
    // or IELaunchURL on Vista or higher. This is done on a 
    // low-integrity thread so we have the correct integrity. 
    DWORD procId = this->m_factory->LaunchBrowserProcess(); 
    CComPtr<IWebBrowser2> pBrowser(this->m_factory->AttachToBrowser(procId)); 
    BrowserWrapper wrapper(pBrowser); 
    this->m_wrapper = wrapper; 
    response = "started"; 
    } 
    else if (strcmp(command.c_str(), "goto\r\n") == 0) 
    { 
    this->m_wrapper.GoToUrl("http://www.google.com/"); 
    response = "navigated"; 
    } 
    else if (strcmp(command.c_str(), "quit\r\n") == 0) 
    { 
    this->m_wrapper.CloseBrowser(); 
    response = "closed"; 
    } 
    else 
    { 
    response = "invalid command"; 
    } 

    return response; 
} 

Интересно, что я прототип этот же механизм в C# до перевода его в неуправляемом C++, чтобы убедиться, что я пытался бы работать, так как мой C++ навыки не тот же уровень, что и мои навыки C#. Излишне говорить, что он отлично работает на C#, но это требование, чтобы этот компонент был написан в неуправляемом коде. Я уверен, что я пропускаю что-то очевидное, что .NET Framework абстрактно, но что бы это ни было, это не очевидно для меня.

Чтобы помочь мне узнать из моей ошибки, я был бы признателен за указатель на то, что делает .NET Framework, чтобы эта работа работала. В версии C# я использую единственный поток с блокировкой ввода-вывода на трубе, как и я (думаю, я) здесь. Если опубликованного фрагмента кода недостаточно, чтобы указать на диагноз, я более чем счастлив предоставить полное решение Visual Studio 2008, демонстрирующее трудности.

+0

В названии упоминается DWebBrowserEvents2, который не показан в коде. –

ответ

2

Ваше приложение становится com-сервером, предоставляя приемники событий. Для приложения com требуется активный «насос сообщений» (ы).

Если ваша блокировка насоса сообщений во время выполнения команды отправки/отправки, это заблокирует IE от вызова вашего приемника.

C# может работать просто для других скрытых окон, которые он имеет, и тем не менее вы настроили остальную часть этого приложения.

+0

Это должно быть то, что происходит здесь. Похоже, что .NET Framework генерирует дополнительные потоки, когда вы погружаете события DWebBrowserEvents2. Этот COM-код взаимодействия должен быть тем, что обрабатывает все кросс-потоковые сортировки при работе в однопоточном консольном приложении (которое обычно не имеет цикла сообщений). Теперь мне просто нужно выяснить, как выполнить что-то подобное в моем неуправляемом коде на C++. – JimEvans

 Смежные вопросы

  • Нет связанных вопросов^_^