#c# #com #interop #bho
#c# #com #взаимодействие #bho
Вопрос:
Я следовал руководству по адресу:http://www.15seconds.com/issue/040331.htm для создания BHO, однако, у меня, похоже, не работает, у меня есть код наблюдателя из examble, где она создает фактический BHO, но когда я пытаюсь ввести тип в моем SetSite, он останавливается, я подозреваю, что получаю исключение.
Это мой пример кода, просто удалил все это, поэтому вместо этого я получаю окно сообщения.
[ClassInterfaceAttribute(ClassInterfaceType.None)]
[GuidAttribute("0CD00297-9A19-4698-AEF1-682FBE9FE88D")]
[ProgIdAttribute("Observer.BrowserMonitor")]
public class BrowserMonitor: IObserver, IObjectWithSite
{
// HRESULT values used
const int E_FAIL = unchecked((int)0x80004005);
const int E_NOINTERFACE = unchecked((int)0x80004002);
public BrowserMonitor()
{
}
protected SHDocVw.IWebBrowser2 m_pIWebBrowser2; // the browser class object
public void SetSite(object pUnkSite)
{
System.Windows.Forms.MessageBox.Show(pUnkSite.ToString());
if (pUnkSite != null)
{
m_pIWebBrowser2 = pUnkSite as SHDocVw.IWebBrowser2;
}
}
public void GetSite(ref System.Guid riid, out object ppvSite)
{
System.Windows.Forms.MessageBox.Show("GetSite");
ppvSite = null;
}
protected void DocumentComplete(object pDisp, ref object URL)
{
System.Windows.Forms.MessageBox.Show("DocumentComplete");
}
protected bool ServiceEnabled()
{
return true;
}
protected void Release()
{
System.Windows.Forms.MessageBox.Show("Release");
}
protected void BeforeNavigate2(object pDisp, ref object url, ref object Flags, ref object TargetFrameName,
ref object PostData, ref object Headers, ref bool Cancel)
{
System.Windows.Forms.MessageBox.Show("BeforeNavigate2");
}
protected void OnQuit()
{
try
{
System.Windows.Forms.MessageBox.Show("OnQuit");
}
catch{}
}
protected void NavigateComplete2(object pDisp, ref object URL)
{
System.Windows.Forms.MessageBox.Show("NavigationComplete2");
}
Моя проблема в моем методе SetSite, как мне выполнить типизацию в браузере любого типа? Если я запущу этот пример в том виде, в каком он есть сейчас, я получу только окно сообщения «GetSite», если я удалю предложение if в SetSite, я также получу SetSite. Кто-нибудь знает, как это сделать?
Комментарии:
1. если я удалю «if», оставив только messagebox, он покажет messagebox. Если я оставлю там структуру «if», я даже не получу всплывающее окно messagebox
Ответ №1:
-
(Не имеет значения для ответа) Вам действительно не следует писать BHO на C #. Да, это можно сделать, но это не очень хорошая идея. Даже с SxS в .NET 4; стоимость инициализации среды CLR для каждой открытой вкладки довольно высока. (Если вы настаиваете, то вы должны, по крайней мере, использовать .NET 4).
-
Методы Get / Set site должны возвращать значение int в соответствии с документацией для
IObjectWithSite
. Ваше объявление интерфейса неверно. -
Ваша
GetSite
реализация должна выглядеть примерно так, как только вы исправите интерфейс:public int GetSite(ref Guid riid, out IntPtr ppvSite) { var pUnk = Marshal.GetIUnknownForObject(_pUnkSite); try { return Marshal.QueryInterface(pUnk, ref riid, out ppvSite); } finally { Marshal.Release(pUnk); } }
В этом случае
_pUnkSite
это объект, который вам был предоставлен вSetSite
. ТакSetSite
будет выглядеть примерно так:private object _pUnkSite; public int SetSite(object pUnkSite) { _pUnkSite = pUnkSite; //Cast pUnkSite to `IWebBrowser2` here and attach events. return 0; }
Как только вы, наконец, разберетесь с некоторыми шаблонными кодами, вы можете использовать свой
pUnkSite
для чего-то вродеIWebBrowser2
для работы с DOM. -
<shamelessplug> Я знаю, что написание C # BHO — плохая идея, потому что я уже делал это. Здесь у меня есть шаблонный проект на GitHub.</shamelessplug>
Комментарии:
1. но не это ли SetSite, которое я ищу, для преобразования в веб-браузер для подключения к событиям навигации. Как я читал tuts, GetSite вызывается после его загрузки с целью освобождения в случае необходимости?
2. @H4mm3rHead Ваш интерфейс C # должен соответствовать определению COM IDL. .NET допустит ошибки сортировки, если что-то не выстроится правильно.
3. Просто изменил оба метода на int и заставил реализацию возвращать 0 (ноль) — это привело к зависанию моего iExplorer, и ничего не ответило, до этого изменения я получил свои ящики сообщений
4. Новая версия: просмотрел ваш tut, тот, за которым я следил, не использовал [PreserveSig] в интерфейсе, теперь я делаю и изменил методы, чтобы возвращать int, все работает (с возвращаемыми типами), и я получаю свой messagebox — по-прежнему нет приведения типов
5. @H4mm3rHead
GetSite
не должен возвращать ноль. Смотрите в моем обновленном примере кода.