envdte - 如何使用 EnvDTE 在 Visual Studio 中获取打开的网页列表

标签 envdte

作为 NuGet 安装的一部分,我们需要在安装完成时打开一个网页。

我们的要求是:

  1. 如果网页尚未在另一个窗口中打开,请在新窗口中的 Visual Studio 中打开该网页。

自己打开网页很简单:

... DTE.ItemOperations.Navigate(WebPageUri.ToString(), EnvDTE.vsNavigateOptions.vsNavigateOptionsNewWindow); ...

问题一直在寻找一种方法来获取当前打开的网页列表,以便我们可以决定是否需要打开某个页面。

我确信解决方案很简单,并且一直在盯着我们看。

我们如何使用 EnvDTE 在 Visual Studio 中获取当前打开的网页列表?

最佳答案

下面列出了问题的解决方案。我怀疑该方法是否是最佳实践,但它确实有效。

Visual Studio 中的 Web 浏览器窗口的“ObjectKind”值为“EnvDTE.Constants.vsWindowKindWebBrowser”。 “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;
    }
}

然后通过以下方式找到打开的网页列表:

IEnumerable<Uri> Urls = VisualStudioWebBrowser.GetWebBrowserWindowUrls(EnvDTEReference);

关于envdte - 如何使用 EnvDTE 在 Visual Studio 中获取打开的网页列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14149785/

相关文章:

c# - 使用 envDTE 以编程方式安装 nupkg

visual-studio-addins - 如何将自定义项目模板和向导集成到 Visual Studio 包中?

c# - T4 模板中无法识别 EnvDTE 类型

c# - 使用 EnvDTE 收集项目中的用户类列表

c# - 通过nuget包添加代码分析规则集

c# - 以编程方式将现有项目添加到新的 VS2012 解决方案失败

visual-studio-2012 - OnEnterBreakMode 不会触发

visual-studio - 在 NuGet Init.ps1 中创建或获取解决方案文件夹

c# - 未返回对通过 AddFromTemplate() 创建的项目项的引用

c# - 获取事件的 Visual Studio 对象