VSIX:获取 DTE 对象

发布于 2024-09-25 01:03:07 字数 1096 浏览 6 评论 0原文

我的 Visual Studio 包需要使用 EnvDTE.DTE 变量,但它总是返回为 null。在阅读了许多黑客之后,他们都说要使用 OnShellPropertyChange() 方法 (IVsShellPropertyEvents),但有时它永远不会触发 - 就好像我的扩展永远不会完成加载一样。

我正在使用 VS2010 并检查 VSSPROPID_Zombie 和 ShellInitialized - 没有工作。 :(

有什么想法吗?这是我正在使用的代码:

public int OnShellPropertyChange(int propid, object var) {
            if (propid == -9053 || (int) __VSSPROPID.VSSPROPID_Zombie == propid) { // -9053 = ShellInit
                try {
                    if ((bool) var == false) {
                        Dte = GetService(typeof (SDTE)) as DTE;
                        Flow.Dte = Dte;

                        var shellService = GetService(typeof (SVsShell)) as IVsShell;

                        if (shellService != null)
                            ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(_cookie));

                        _cookie = 0;
                    }
                } catch {

                }
            }

            return VSConstants.S_OK;
        }

编辑:在实验实例下,它运行完美,大约需要 5 秒来初始化。但是,一旦部署为 VSIX - 它根本不会触发。

My Visual Studio package requires the use of an EnvDTE.DTE variable, but it always gets back as null. After reading up on many hacks, all of them say to use the OnShellPropertyChange() method (IVsShellPropertyEvents), but sometimes it just never fires - as if my extension never finishes loading.

I'm using VS2010 and checking against both VSSPROPID_Zombie and ShellInitialized - no work. :(

Any ideas? This is the code I'm using:

public int OnShellPropertyChange(int propid, object var) {
            if (propid == -9053 || (int) __VSSPROPID.VSSPROPID_Zombie == propid) { // -9053 = ShellInit
                try {
                    if ((bool) var == false) {
                        Dte = GetService(typeof (SDTE)) as DTE;
                        Flow.Dte = Dte;

                        var shellService = GetService(typeof (SVsShell)) as IVsShell;

                        if (shellService != null)
                            ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(_cookie));

                        _cookie = 0;
                    }
                } catch {

                }
            }

            return VSConstants.S_OK;
        }

EDIT: Under Experimental Instance, it works perfectly and takes about 5 seconds to initialize. However, once deployed as VSIX - it simply doesn't fire.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

待天淡蓝洁白时 2024-10-02 01:03:07

尝试以下命令:

dte = Package.GetGlobalService(typeof(DTE)) as DTE2;

Try the following command:

dte = Package.GetGlobalService(typeof(DTE)) as DTE2;
违心° 2024-10-02 01:03:07

如果您有 MEF 组件,获取 DTE 对象的最简单方法如下:

首先添加对 Microsoft.VisualStudio.Shell.Immutable.10 的引用。然后为 SVsServiceProvider 添加 MEF 导入。该对象有一个 GetService 方法,可以查询 DTE

[ImportingConstructor]
public MyComponent(SVsServiceProvider serviceProvider) {
  _DTE dte = (_DTE)serviceProvider.GetService(typeof(_DTE));
}

If you have a MEF component the easiest way to get to a DTE object is as follows

First add a reference to Microsoft.VisualStudio.Shell.Immutable.10. Then add a MEF import for SVsServiceProvider. This object has a GetService method which can be queried for DTE

[ImportingConstructor]
public MyComponent(SVsServiceProvider serviceProvider) {
  _DTE dte = (_DTE)serviceProvider.GetService(typeof(_DTE));
}
冷默言语 2024-10-02 01:03:07

我在这里看到几个问题:

  • 您确实应该使用 __VSSPROPID4.VSSPROPID_ShellInitialized (在 Microsoft.VisualStudio.Shell.Interop.10.0 中定义)而不是 -9083 以提高可读性
  • 您应该检查 ShellInitialized 是否设置为 true (尽管检查 Zombie 是否为 false 是正确的)
  • 请记住,ShellInitialized 将一次更改为 true ...在 VS 启动时。如果您的包已注册为在启动时自动加载(这可能在 VS 完全准备好之前发生),则检查它是正确的方法。但是,大多数包不应在启动时自动加载,而是根据需要包代码的某些用户操作按需加载。然后,您可以在包类的 Initialize 方法中检查 DTE 服务。

I see a couple of problems here:

  • You really should be using __VSSPROPID4.VSSPROPID_ShellInitialized (defined in Microsoft.VisualStudio.Shell.Interop.10.0) instead of -9083 for readability
  • You should be checking for ShellInitialized being set to true (although checking for Zombie going to false is correct)
  • Keep in mind that ShellInitialized will change to true once...on startup of VS. Checking for it is the right approach if your package is registered to auto-load on startup (which may happen before VS is fully ready to go). However, most packages should not auto-load on startup, but rather load on-demand from some user action requiring your package code. You can then check for the DTE service in your package class Initialize method.
青衫负雪 2024-10-02 01:03:07

我知道您已经选择了一个答案,但您确实指定了您不想使用 MEF,所以我想我会为了完整性而发布一个替代方案....;p


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using EnvDTE;
using EnvDTE80;

namespace DTETesting
{
    class Program
    {
        const string ACTIVE_OBJECT = "VisualStudio.DTE.10.0";
        static void Main(string[] args)
        {
            EnvDTE80.DTE2 MyDte;
            MyDte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject(ACTIVE_OBJECT);
            Console.WriteLine("The Edition is "+MyDte.Edition);
            Console.ReadLine();
        }
    }
}

I know you selected an answer already but you did specify that you didnt want to use the MEF so I thought I would post an alternative just for the sake of completeness....;p


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using EnvDTE;
using EnvDTE80;

namespace DTETesting
{
    class Program
    {
        const string ACTIVE_OBJECT = "VisualStudio.DTE.10.0";
        static void Main(string[] args)
        {
            EnvDTE80.DTE2 MyDte;
            MyDte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject(ACTIVE_OBJECT);
            Console.WriteLine("The Edition is "+MyDte.Edition);
            Console.ReadLine();
        }
    }
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文