11

設計時のコードをコーディングしています。このスニペットを使用したい: (ここにあります)

var dte = (EnvDTE.DTE) GetService(typeof(EnvDTE.DTE));
if (dte != null)
{
    var solution = dte.Solution;
    if (solution != null)
    {
        string baseDir = Path.GetDirectoryName(solution.FullName);
    }
}

問題は、これがコンパイルされないことです。(GetService は既知のメソッド呼び出しではありません) Microsoft.VisualStudio.Shell (および Microsoft.VisualStudio.Shell.10.0) を追加しようとしましたが、役に立ちませんでした。

インターネットで調べてみると、これを呼び出すには IServiceProvider が必要であることがわかりました。

ただし、IServiceProvider を取得する方法を示すすべての例では、EnvDTE を使用しています。

したがって、現在の EnvDTE を取得するには、IServiceProvider が必要です。しかし、IServiceProvider を取得するには、EnvDTE が必要です。(バケツに穴があいてます…)

だから、ここに私の質問があります:

通常の WPF アプリケーションでは、EnvDTEの現在のインスタンスを取得するにはどうすればよいですか?

注: EnvDTE の古いインスタンスを探しているわけではありません。現在の Visual Studio インスタンス用に 1 つ必要です (一度に 3 ~ 4 個の Visual Studio インスタンスを実行しています)。

4

5 に答える 5

8

この質問には、あなたが探している答えがあります。

Visual C# 2010 で DTE2 オブジェクトの参照を取得する

具体的には

https://stackoverflow.com/a/4724924/858142

コードは次のとおりです。

用途:

using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using EnvDTE;
using Process = System.Diagnostics.Process;

方法:

[DllImport("ole32.dll")]
private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);
[DllImport("ole32.dll")]
private static extern void GetRunningObjectTable(int reserved,
                                                 out IRunningObjectTable prot);
internal static DTE GetCurrent()
{
   //rot entry for visual studio running under current process.
   string rotEntry = String.Format("!VisualStudio.DTE.10.0:{0}",
                                    Process.GetCurrentProcess().Id);
   IRunningObjectTable rot;
   GetRunningObjectTable(0, out rot);
   IEnumMoniker enumMoniker;
   rot.EnumRunning(out enumMoniker);
   enumMoniker.Reset();
   IntPtr fetched = IntPtr.Zero;
   IMoniker[] moniker = new IMoniker[1];
   while (enumMoniker.Next(1, moniker, fetched) == 0)
   {
       IBindCtx bindCtx;
       CreateBindCtx(0, out bindCtx);
       string displayName;
       moniker[0].GetDisplayName(bindCtx, null, out displayName);
       if (displayName == rotEntry)
       {
           object comObject;
           rot.GetObject(moniker[0], out comObject);
           return (DTE)comObject;
       }
   }
   return null;
}

他の回答が示すように、これはデバッグ中には機能しません。

于 2012-06-12T14:24:03.903 に答える
4

IServiceProviderが必要で、その GetService メソッドを呼び出すことができます。
dte = (DTE)serviceProvider.GetService(typeof(DTE));

問題は、IServiceProviderインターフェイスへの参照を取得する方法です。

たとえば、ツール ウィンドウ ( ToolWindowPane から継承) を使用して VsPackage を作成ている場合、ToolWindow クラス自体が IServiceProvider を実装します。このような場合、WPF コントロールで IServiceProvider を使用する場合は、ツール ウィンドウ コンストラクターでそのインスタンスを作成し、コントロールのコンストラクターに引数として渡すだけです。this

[Guid("f716c629-b8e3-4ab2-8dbd-8edd67165609")]
public class MyToolWindow : ToolWindowPane
{
    /// <summary>
    /// Standard constructor for the tool window.
    /// </summary>
    public MyToolWindow() :
        base(null)
    {
        ...
        // This is the user control hosted by the tool window
        base.Content = new MyControl(this);
    }

コントロールのコンストラクターはIServiceProvider引数として取得します:

public MyControl(IServiceProvider _serviceProvider)
于 2012-06-12T06:38:53.590 に答える
0

このコードを使用してこれを正常に実行しました。

System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0")

ただし、完全ではありません。VisualStudioのインスタンスが1つだけ実行されている必要があります(複数ある場合、メソッドはそのうちの1つを返しますが、どれを制御することはできません)。

于 2012-06-05T22:36:40.257 に答える
0

この同様の質問に対する回答を投稿しました: Get the reference of the DTE2 object in Visual C# 2010

私のアプローチは、DTE2.Solution.FullName を実行中のアセンブリ パスと比較して、Quickhorns の回答と同じ ROT 列挙を使用して可能な候補をフィルター処理した後、適切な Visual Studio インスタンスを見つけることです。

于 2012-10-23T16:22:00.603 に答える