问题
I have followed the tutorial at: http://www.15seconds.com/issue/040331.htm for making a BHO, however i doesnt seem to work for me, i have the Observer code from the examble, where she creates the actual BHO, but when i try to typecast in my SetSite it stops, i suspect i get an exception.
This is my sample code, just stripped it all bare, so i get a messagebox instead.
[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");
}
My problem is in my SetSite method, how do i typecast to a browser of any sorts? If i run this sample as it is now, I only get the "GetSite" messagebox, if I remove the if sentence in the SetSite i also get the SetSite. Does anyone know how to do this?
回答1:
(Non vital to the answer) You really shouldn't be writing a BHO in C#. Yes it can be done, but it isn't a good idea. Even with SxS in .NET 4; the cost of initializing the CLR for every tab opened is pretty high. (If you insist then you should at least be using .NET 4).
The Get / Set site methods should return an int according to the documentation for IObjectWithSite. Your interface declaration is wrong.
Your
GetSite
implementation should look something like this once you get the interface fixed up: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); } }
In this case,
_pUnkSite
is the object that you were given atSetSite
. SoSetSite
will look something like this:private object _pUnkSite; public int SetSite(object pUnkSite) { _pUnkSite = pUnkSite; //Cast pUnkSite to `IWebBrowser2` here and attach events. return 0; }
Once you've finally gotten some of the boilerplate code taken care of, you can cast your
pUnkSite
to something likeIWebBrowser2
to work with the DOM.<shamelessplug>I know that writing a C# BHO is a bad idea because I have done so. I have a boilerplate GitHub project here.</shamelessplug>
来源:https://stackoverflow.com/questions/8040904/getting-url-and-html-through-a-bho-setsite-throws-an-exception