我已经按照教程:http://www.15seconds.com/issue/040331.htm制作了一个BHO,但是我似乎并没有为我工作,我有来自考试的观察员代码,在那里她创建了实际的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”消息框,如果我删除了SetSite中的if句子,我也得到了SetSite。有谁知道怎么做?
答案 0 :(得分:1)
(对答案不重要)你真的不应该在C#中写一个BHO。是的,它可以做到,但这不是一个好主意。即使在.NET 4中使用SxS;为每个打开的选项卡初始化CLR的成本非常高。 (如果你坚持,那么你至少应该使用.NET 4。)
Get / Set站点方法应根据IObjectWithSite
的文档返回int。你的界面声明是错误的。
一旦修复界面,您的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是个坏主意because I have done so。我有一个样板GitHub项目here。< / shamelessplug>