Вызов методов C # BHO из Javascript

Я пытаюсь понять, как вызывать методы C # в моем объекте BHO из Javascript на странице. Я нашел множество страниц о том, как это сделать на C ++ / ATL / Com, например:

Параметры объектов помощника браузера и сценариев

Вызов метода BHO из Javascript?

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

Я использую C # 4.0.

Вот соответствующие части кода:

using SHDocVw;
using mshtml;
using System.Runtime.InteropServices;

[ComVisible(true),
 Guid("300736C4-DCDA-4DB0-90AD-4510A12EBBC6"),
 ClassInterface(ClassInterfaceType.None),
 ProgId("My Extension")]
public class BrowserHelperObject : IObjectWithSite
{
    const int DISPATCH_PROPERTYPUT = 4;
    const int FDEX_NAME_ENSURE = 2;
    const uint LOCALE_USER_DEFAULT = 0x0400;

    WebBrowser browser;

    ...
    public void OnDocumentComplete(dynamic frame, ref dynamic url)
    {
        ...
        var window = browser.Document.parentWindow;

        int pid = 0;
        window.GetDispId("myExtension", FDEX_NAME_ENSURE, ref pid);

        System.Runtime.InteropServices.ComTypes.DISPPARAMS dispParms = new System.Runtime.InteropServices.ComTypes.DISPPARAMS();
        dispParms.cArgs = 1;
        dispParms.cNamedArgs = 0;
        dispParms.rgvarg = ???;
        dispParms.rgdispidNamedArgs = IntPtr.Zero;
        System.Runtime.InteropServices.ComTypes.EXCEPINFO einfo = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
        window.Invoke(pid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, ref dispParms, this, ref einfo);            
        ...
    }

person fixedpoint    schedule 15.02.2012    source источник


Ответы (2)


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

Убедитесь, что вы правильно открыли вспомогательный объект браузера:

[ComVisible(true),
 Guid("DA8EA345-02AE-434E-82E9-448E3DB7629E"),
 ClassInterface(ClassInterfaceType.None), ProgId("MyExtension"),
 ComDefaultInterface(typeof(IExtension))]
public class BrowserHelperObject : IObjectWithSite, IExtension
{
    ...
    public int Foo(string s) { ... }
    ...
    public void OnDocumentComplete(dynamic frame, ref dynamic url)
    {
        ...
        dynamic window = browser.Document.parentWindow;
        IExpando windowEx = (IExpando)window;
        windowEx.AddProperty("myExtension");
        window.myExtension = this;
        ...
    }
    ...
}

И вам понадобится определение для ваших расширений:

[ComVisible(true),
 Guid("4C1D2E51-018B-4A7C-8A07-618452573E42"),
 InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IExtension
{
    [DispId(1)]
    int Foo(string s);
    ...
}

Вы можете получить доступ к своему вспомогательному объекту браузера в javascript следующим образом:

var result = window.myExtension.Foo("bar");

или просто

var result = myExtension.Foo("bar");

Вот и все. Хватит биться головой об стену и празднуй!

person fixedpoint    schedule 16.02.2012
comment
Не сожалейте, что ответили на свой вопрос .. Потому что: 1) люди ищут ответ, а не ответившего человека; 2) у вас есть проблема, и вы можете ответить, это означает, что вы работали над этим. 'серьезно хорошая вещь ... поздравляю .... - person Tirumudi; 03.08.2012
comment
Привет, фиксированная точка. Не могли бы вы выложить полностью рабочий прототип? Я попытался точно воспроизвести это, и мое window.myExtension остается 'undefined'. Я разместил этот вопрос с полным исходным кодом здесь - person g.pickardou; 25.02.2013
comment
Для меня это терпит неудачу, как только я загружаю некоторый javascript на свою страницу - на страницах без каких-либо ссылок на внешние скрипты это нормально, как только у меня есть ссылка на внешний скрипт, он терпит неудачу. Также странно, как только он начинает давать сбой, он продолжает отказывать на страницах, на которых раньше работал. - person Andrew Barrett; 10.04.2013
comment
У меня это тоже не работает. Был бы очень признателен за рабочий пример! - person BeneGal; 04.12.2013
comment
Если это не работает, попробуйте следующее: объект браузера должен быть экземпляром «IWebBrowser», а не «IWebBrowser2». - person Robert Petz; 17.10.2014
comment
Возможно, вы не включили ComDefaultInterface (typeof (IExtension)) в свой класс реализации, поэтому он не работает - person Amel Music; 04.03.2015
comment
Если вы, как и я, использовали код в stackoverflow. com / questions / 5643819 /, чтобы создать свое расширение, тогда то, что говорит @AmelMusic, - это то, чего не хватает. Спасибо чувак! - person makhdumi; 05.03.2015
comment
В моем случае GUID для IExtension другой. Я использовал C:\>reg query HKLM /s /f IExtension /d /e /c, чтобы получить такой результат HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{B05651CD-9B10-425E-B616-1FCD828DB3B1}, а идентификатор указан в фигурных скобках. - person Kinjal Dixit; 01.10.2015

Кроме того, после добавления свойства вам необходимо убедиться, что COM-ссылки окна и windowEx освобождены.

person Amel Music    schedule 09.03.2015
comment
Не могли бы вы подробнее рассказать об этом. - person Mr. Usama; 25.06.2020