この問題の解決策を以下に示します。このアプローチがベストプラクティスであるとは思えませんが、うまくいくようです。
Visual Studio の Web ブラウザ ウィンドウには、「EnvDTE.Constants.vsWindowKindWebBrowser」の「ObjectKind」値があります。「Object」の値は Internet Explorer ブラウザで、「IWebBrowser2」を実装しています。「IWebBrowser2」は .Net ではありませんが、「System.Windows.Forms.WebBrowser」は (どうやら) 「IWebBrowser2」のラッパーです。「System.Windows.Forms.WebBrowser」にはオーバーライド可能な「AttachInterfaces」メソッドがあり、ウィンドウ オブジェクトを渡して、「System.Windows.Forms.WebBrowser」に面倒な作業を任せることができます。
最終結果は次のとおりです。
public class VisualStudioWebBrowser : System.Windows.Forms.WebBrowser
{
protected VisualStudioWebBrowser(object IWebBrowser2Object)
{
this.IWebBrowser2Object = IWebBrowser2Object;
}
protected object IWebBrowser2Object { get; set; }
public static void Evaluate(EnvDTE.Window WindowReference, Action<System.Windows.Forms.WebBrowser> OnEvaluate)
{
//Note: Window of EnvDTE.Constants.vsWindowKindWebBrowser type contains an IWebBrowser2 object
if (VisualStudioWebBrowser.IsWebBrowserWindow(WindowReference))
{
using (System.Threading.ManualResetEvent evt = new System.Threading.ManualResetEvent(false))
{
System.Threading.Thread STAThread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart((o) =>
{
try
{
using (VisualStudioWebBrowser Browser = new VisualStudioWebBrowser(o))
{
try
{
OnEvaluate.Invoke((System.Windows.Forms.WebBrowser)Browser);
}
catch { }
}
}
catch { }
evt.Set();
}));
STAThread.SetApartmentState(System.Threading.ApartmentState.STA);
STAThread.Start(WindowReference.Object);
evt.WaitOne();
}
}
}
public static bool IsWebBrowserWindow(EnvDTE.Window WindowReference)
{
return (WindowReference != null && WindowReference.ObjectKind.Equals(EnvDTE.Constants.vsWindowKindWebBrowser, StringComparison.InvariantCultureIgnoreCase));
}
public static IEnumerable<EnvDTE.Window> GetWebBrowserWindows(EnvDTE.DTE EnvDTEReference)
{
List<EnvDTE.Window> BrowserWindows = new List<EnvDTE.Window>();
foreach (EnvDTE.Window WindowReference in EnvDTEReference.Windows)
{
if (VisualStudioWebBrowser.IsWebBrowserWindow(WindowReference) == true)
{
BrowserWindows.Add(WindowReference);
}
}
return BrowserWindows;
}
public static Uri GetWebBrowserWindowUrl(EnvDTE.Window WindowReference)
{
Uri BrowserUrl = new Uri("", UriKind.RelativeOrAbsolute);
VisualStudioWebBrowser.Evaluate(WindowReference, new Action<System.Windows.Forms.WebBrowser>((wb) =>
{
BrowserUrl = wb.Url;
}));
return BrowserUrl;
}
public static IEnumerable<Uri> GetWebBrowserWindowUrls(EnvDTE.DTE EnvDTEReference)
{
List<Uri> BrowserUrls = new List<Uri>();
foreach (EnvDTE.Window BrowserWindow in VisualStudioWebBrowser.GetWebBrowserWindows(EnvDTEReference))
{
try
{
Uri BrowserUrl = VisualStudioWebBrowser.GetWebBrowserWindowUrl(BrowserWindow);
if (String.IsNullOrWhiteSpace(BrowserUrl.LocalPath) == false)
{
BrowserUrls.Add(BrowserUrl);
}
}
catch { }
}
return BrowserUrls;
}
protected override void AttachInterfaces(object nativeActiveXObject)
{
base.AttachInterfaces(this.IWebBrowser2Object);
//base.AttachInterfaces(nativeActiveXObject);
}
protected override void DetachInterfaces()
{
base.DetachInterfaces();
this.IWebBrowser2Object = null;
}
}
開いている Web ページのリストは、次の方法で検索されます。
IEnumerable<Uri> Urls = VisualStudioWebBrowser.GetWebBrowserWindowUrls(EnvDTEReference);