I've seen a lot of questions about implementing KB196340 in managed code as well as getting an IWebBrowser2 interface from an IHTMLDocument2 or IHTMLWindow2 interface. I had the same questions, so I dug in and below is what I came up with. I have yet to have any problems with it, but it may need some work with releasing the COM objects (feel free to comment if you have suggestions.) IEnumUnknown [ ComImport, Guid("00000100-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown) ] public interface IEnumUnknown { [PreserveSig] int Next( [In, MarshalAs(UnmanagedType.U4)] int celt, [Out, MarshalAs(UnmanagedType.IUnknown)] out object rgelt, [Out, MarshalAs(UnmanagedType.U4)] out int pceltFetched ); [PreserveSig] int Skip( [In, MarshalAs(UnmanagedType.U4)] int celt ); void Reset(); void Clone( out IEnumUnknown ppenum ); }
[
ComImport,
Guid("00000100-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
public interface IEnumUnknown
{
[PreserveSig]
int Next(
[In, MarshalAs(UnmanagedType.U4)] int celt,
[Out, MarshalAs(UnmanagedType.IUnknown)] out object rgelt,
[Out, MarshalAs(UnmanagedType.U4)] out int pceltFetched
);
int Skip(
[In, MarshalAs(UnmanagedType.U4)] int celt
void Reset();
void Clone(
out IEnumUnknown ppenum
}
[Flags()]
public enum tagOLECONTF
OLECONTF_EMBEDDINGS = 1,
OLECONTF_LINKS = 2,
OLECONTF_OTHERS = 4,
OLECONTF_ONLYUSER = 8,
OLECONTF_ONLYIFRUNNING = 16,
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000011B-0000-0000-C000-000000000046")]
public interface IOleContainer
int ParseDisplayName(
[In, MarshalAs(UnmanagedType.Interface)] object pbc,
[In, MarshalAs(UnmanagedType.BStr)] string pszDisplayName,
[Out, MarshalAs(UnmanagedType.LPArray)] int[] pchEaten,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] ppmkOut
int EnumObjects(
[In, MarshalAs(UnmanagedType.U4)] tagOLECONTF grfFlags,
int LockContainer(
bool fLock
public IWebBrowser2 GetBrowserFromWindow(IHTMLWindow2 win)
if(win == null)
throw new ArgumentNullException("win");
IWebBrowser2 result = null;
//if the document is the top level document, we don't have to look for it
if(win.document == this.CurrentDocument)
result = this.IWebBrowser2; //internal reference to the top-level IWebBrowser2
else
//get the OLE container from the window's parent
IOleContainer oc = win.parent.document as IOleContainer; //OC ALLOC
//get the OLE enumerator for the embedded objects
int hr = 0;
IEnumUnknown eu;
hr = oc.EnumObjects(tagOLECONTF.OLECONTF_EMBEDDINGS, out eu); //EU ALLOC
Marshal.ReleaseComObject(oc); //OC FREE
Marshal.ThrowExceptionForHR(hr);
Guid IID_IWebBrowser2 = typeof(SHDocVw.IWebBrowser2).GUID;
object pUnk = null;
int fetched = 0;
const int MAX_FETCH_COUNT = 1;
//get the first embedded object
hr = eu.Next(MAX_FETCH_COUNT, out pUnk, out fetched); //PUNK ALLOC
//while sucessfully get a new embedding, continue
for(int i = 0; HRESULTS.S_OK == hr; i++)
//QI pUnk for the IWebBrowser2 interface
SHDocVw.IWebBrowser2 brow = pUnk as SHDocVw.IWebBrowser2;
if(brow != null)
//if the document for this browser matches the one passed in, we found it
if(brow.Document == win.document)
result = brow;
break;
Marshal.ReleaseComObject(brow); //PUNK FREE
} //if(brow != null)
//get the next ebmedded object
} //for(int i = 0; HRESULTS.S_OK == hr; i++)
Marshal.ReleaseComObject(eu); //EU FREE
return result;
Remember Me
a@href@title, b, blockquote@cite, em, i, strike, strong, sub, super, u
Page rendered at Saturday, October 11, 2008 1:57:42 AM (Central Daylight Time, UTC-05:00)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.