根据this question,我尝试了以下内容:
EnvDTE80.DTE2 dte = ServiceProvider.GlobalProvider.GetService(typeof(EnvDTE80.DTE2)) as EnvDTE80.DTE2;
没有运气,空对象。
但基于this MSDN doc,我尝试了以下内容。
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.12.0");
这有效并给了我DTE2对象。
从那时起,我尝试了以下this questin我尝试了以下内容:
VersionControlExt vce = dte.GetObject("Microsoft.VisualStudio.TeamFoundation.VersionControl.VersionControlExt") as VersionControlExt;
没有运气,空对象。
有一点需要注意的是,根据最后一个问题,它说要使用Microsoft.VisualStudio.TeamFoundation.Client
命名空间。问题是,我无法找到它。我甚至确保用相同的名称引用dll。我能够引用所有其他名称空间。
最后,我尝试了teamfoundation.blogspot中的以下内容。
EnvDTE.IVsExtensibility extensibility = GetService(typeof(EnvDTE.IVsExtensibility)) as EnvDTE.IVsExtensibility;
EnvDTE80.DTE2 dte = extensibility.GetGlobalsObject(null).DTE as EnvDTE80.DTE2;
//Followed by this to get the Version
VersionControlExt vce = dte.GetObject("Microsoft.VisualStudio.TeamFoundation.VersionControl.VersionControlExt") as VersionControlExt;
这很有用。
所以,虽然我设法获得了DTE2并从中获得了VersionControlExt,但我觉得我已经进入了Cargo Cult程序员的土地,并且更愿意理解为什么这些都是有效的方式。获得DTE2,但他们的行为都不同。
答案 0 :(得分:6)
从扩展中获取DTE实例的正确方法是使用扩展API为该扩展提供的方式。
对于正在使用的包:
base.GetService(typeof运算(EnvDTE.DTE))
(请注意" base"指的是MPF Package类,因此您使用的是可扩展性API。如果您在帖子中使用全局提供程序,那么您还使用了可扩展性API)
但与此无关的是,标记为自动加载的软件包会发生这两个问题:
1)当启动VS时将包标记为自动加载时返回的DTE值为null(而不是在需要时加载)
2)DTE不为空,但是某些属性(如DTE.MainWindow)仍然为空,因为VS实例尚未完全初始化。
要防止这两种情况,您必须订阅VS IDE已完全初始化且不处于僵尸状态的通知。看看你必须使用的可怕的黑客:HOWTO: Get an EnvDTE.DTE instance from a Visual Studio package.
从扩展中获取DTE实例的错误方法是使用COM自动化(通过.NET Framework API)而不是使用可扩展性API(MSDN文档提到这种方法很可怕):
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.12.0");
因为COM自动化中的GetObject(ProgId)(或者诸如Marshal.GetActiveObject(ProgId)之类的.NET包装器)用于附加到所需ProgId的运行实例(" VisualStudio.DTE.12.0&#34 ;)和如果您有多个正在运行的实例,您的扩展程序可能会结束获取对另一个实例的引用!。