C# IE BHO: как маршалировать объекты DOM в рабочий поток?

Я пытаюсь написать вспомогательный объект браузера (BHO) на C#, который манипулирует DOM на отдельная нить. Я видел несколько других вопросов, связанных с этим, и ответ, кажется, «вам нужно маршалировать объекты DOM из потока, в котором они были созданы, в ваш рабочий поток». Хороший совет, и он имеет смысл, но я не могу найти примеров C#, как это сделать. Есть некоторые расплывчатые указатели на некоторые API-интерфейсы P/Invoke, которые необходимо использовать, но мне трудно понять, как реализовать это в BHO.

Я лучше всего учусь на примерах, и в документации очень мало примеров такого рода вещей для .NET. Может ли кто-нибудь указать мне на пример, где в контексте управляемого кода BHO управление DOM осуществляется через рабочий поток?


person JimEvans    schedule 23.06.2010    source источник
comment
Вы действительно не должны писать управляемые расширения IE. Вы бы сделали это изначально, используя CoMarshallInterThreadInterfaceInStream(). msdn.microsoft.com/en-us/library/ms693316 (VS.85).aspx   -  person i_am_jorf    schedule 24.06.2010
comment
Конечно, это не лучший выбор, и неуправляемый код был бы лучше, но в .NET framework есть множество классов, невероятно полезных для моих целей (HttpListener, смехотворно простая реализация Sockets и т. д.). Предположим, что BHO предназначен для использования персоналом QA в качестве инструмента автоматизации тестирования.   -  person JimEvans    schedule 24.06.2010
comment
С поддержкой .NET 4 Side by Side (SxS) должна быть возможность создавать управляемые расширения без проблем старой версии, упомянутых здесь: msmvps.com/blogs/vcsjones/archive/2010/05/23/. Однако производительность может быть проблемой.   -  person David Lynch    schedule 21.07.2010


Ответы (1)


Вам не нужно выполнять маршалинг вручную; управляемая среда выполнения обрабатывает любой маршалинг COM-объекта между подразделениями от вашего имени.

Вот пример; этот образец управляемого BHO ожидает, пока не сработает событие DocumentComplete, и запустит фоновый поток ThreadPool, который ждет секунду, а затем меняет заголовок страницы на «Hello, StackOverflow!» и добавляет новый текстовый узел со специальным сообщением:

private void OnDocumentComplete(object frame, ref object urlObj)
{
    System.Threading.ThreadPool.QueueUserWorkItem((o) =>
    {
        System.Threading.Thread.Sleep(1000);
            HTMLDocument document = (HTMLDocument)this.browser.Document;
            document.title = "Hello, StackOverflow!";

            IHTMLDOMNode greetings = document.createTextNode("Hi there!");

            IHTMLDOMNode body = document.body as IHTMLDOMNode;
            body.insertBefore(greetings, body.firstChild);                
    }, this.browser);
}

#region IObjectWithSite Members

int IObjectWithSite.SetSite(object site)
{
    if (site != null)
    {
        this.browser = (WebBrowser)site;
        this.browser.DocumentComplete +=
         new DWebBrowserEvents2_DocumentCompleteEventHandler(
          this.OnDocumentComplete);
    }
    else
    {
        if (this.browser != null)
        {
            this.browser.DocumentComplete -=
             new DWebBrowserEvents2_DocumentCompleteEventHandler(
              this.OnDocumentComplete);
            this.browser = null;
        }
    }
    return 0;
}

int IObjectWithSite.GetSite(ref Guid guid, out IntPtr ppvSite)
{
    IntPtr punk = Marshal.GetIUnknownForObject(this.browser);
    int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
    Marshal.Release(punk);

    return hr;
}

#endregion
person Andy Hopper    schedule 22.07.2010