WebBrowserを拡張してWebBrowser2イベントを拾う際にInvalidActiveXStateExceptionが出てしまいます。
概要
・C#においてWebBrowserで特定のサイトにアクセスした際にボタンをクリックすると、IEが立ち上がってしまいました。そのため、新規ウィンドウを開こうとするときにNewWindow2イベントを拾ってWebBrowser内で立ち上げるためにWebBrowserを拡張してNewWindow2イベントを扱えるようにしようとしています。
・主にこのWebページ(新規ウィンドウを自前のForm(WebBrowser)で開きたい)を参考に下記のようなコードを足しました。
public class ExtendedWebBrowser : WebBrowser
{
private AxHost.ConnectionPointCookie cookie;
private WebBrowser2EventHelper helper;
[DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)]
[DispIdAttribute(200)]
public object Application
{
get
{
if (this.ActiveXInstance == null)
{
throw new AxHost.InvalidActiveXStateException("Application", AxHost.ActiveXInvokeKind.PropertyGet);
}
return this.ActiveXInstance.GetType().InvokeMember("Application", System.Reflection.BindingFlags.GetProperty, null, this.ActiveXInstance, null);
}
}
[DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)]
[DispIdAttribute(552)]
public bool RegisterAsBrowser
{
get
{
if (this.ActiveXInstance == null)
{
throw new AxHost.InvalidActiveXStateException("RegisterAsBrowser", AxHost.ActiveXInvokeKind.PropertyGet);
}
return (bool)this.ActiveXInstance.GetType().InvokeMember("RegisterAsBrowser", System.Reflection.BindingFlags.GetProperty, null, this.ActiveXInstance, null);
}
set
{
if (this.ActiveXInstance == null)
{
throw new AxHost.InvalidActiveXStateException("RegisterAsBrowser", AxHost.ActiveXInvokeKind.PropertySet);
}
this.ActiveXInstance.GetType().InvokeMember("RegisterAsBrowser", System.Reflection.BindingFlags.SetProperty, null, this.ActiveXInstance, new object[] { value });
}
}
[PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void CreateSink()
{
base.CreateSink();
helper = new WebBrowser2EventHelper(this);
cookie = new AxHost.ConnectionPointCookie(this.ActiveXInstance, helper, typeof(DWebBrowserEvents2));
}
[PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void DetachSink()
{
if (cookie != null)
{
cookie.Disconnect();
cookie = null;
}
base.DetachSink();
}
public event WebBrowserNewWindow2EventHandler NewWindow2 = (o, e) => { };
protected virtual void OnNewWindow2(WebBrowserNewWindow2EventArgs e)
{
NewWindow2(this, e);
}
private class WebBrowser2EventHelper : StandardOleMarshalObject, DWebBrowserEvents2
{
private ExtendedWebBrowser parent;
public WebBrowser2EventHelper(ExtendedWebBrowser parent)
{
this.parent = parent;
}
public void NewWindow2(ref object ppDisp, ref bool cancel)
{
var e = new WebBrowserNewWindow2EventArgs(ppDisp);
this.parent.OnNewWindow2(e);
ppDisp = e.ppDisp;
cancel = e.Cancel;
}
}
}
public delegate void WebBrowserNewWindow2EventHandler(object sender, WebBrowserNewWindow2EventArgs e);
public class WebBrowserNewWindow2EventArgs : CancelEventArgs
{
public object ppDisp { get; set; }
public WebBrowserNewWindow2EventArgs(object ppDisp)
{
this.ppDisp = ppDisp;
}
}
[ComImport, Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[TypeLibType(TypeLibTypeFlags.FHidden)]
public interface DWebBrowserEvents2
{
[DispId(251)]
void NewWindow2([InAttribute(), OutAttribute(), MarshalAs(UnmanagedType.IDispatch)] ref object ppDisp, [InAttribute(), OutAttribute()] ref bool cancel);
}
・これを使用するクラスは下記のWebBrowserを管理するクラス(抜粋)です。
private void WebBrowser_NewWindow2(object sender, WebBrowserNewWindow2EventArgs e)
{
// 新しい WebBrowser の初期化
WebBrowser = new ExtendedWebBrowser();
WebBrowser.Dock = DockStyle.Fill;
WebBrowser.NewWindow2 += WebBrowser_NewWindow2;
// this.TabPage1 = new TabPage();
// this.TabPage1.Controls.Add(WebBrowser);
// this.TabControl.Controls.Add(TabPage1);
// this.TabControl.SelectedTab = TabPage1;
// 新しい WebBrowser に表示させる設定
e.ppDisp = this.WebBrowser.Application;
this.WebBrowser.RegisterAsBrowser = true;
}
public async Task WaitNextPage()
{
await this.WaitDocumentLoad();
this.SwitchToRootFrame();
WebBrowser.NewWindow2 += new WebBrowserNewWindow2EventHandler(WebBrowser_NewWindow2);
this.SavePage();
}
・実行時にExtendedWebBrowserクラスの
return this.ActiveXInstance.GetType().InvokeMember("Application", System.Reflection.BindingFlags.GetProperty, null, this.ActiveXInstance, null);
で 'System.Windows.Forms.AxHost.InvalidActiveXStateException' の例外が発生してしまいます。
動作環境
・.NET Frame Work 4.5
・Visual Studio2013
補足
・サイト遷移の様子はアプリ利用者に表示しないため、WebBrowserコントロールはFormに紐づけていません。
よろしくお願いします。