11

私はいくつかのデザインタイムコードをコーディングしています。アドインをコーディングしていないときに現在のEnvDTEまたはIServiceProviderを取得する

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

問題は、これはコンパイルできないということである(hereを発見):私はこのスニペットを使用します。 (GetServiceは既知のメソッド呼び出しではありません)Microsoft.VisualStudio.Shell(およびMicrosoft.VisualStudio.Shell.10.0)を追加しようとしましたが、それは役に立ちませんでした。

インターネットを見渡すと、これを呼び出すためにIServiceProviderが必要であることがわかりました。

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

したがって、現在のEnvDTEを取得するには、IServiceProviderが必要です。しかし、IServiceProviderを取得するにはEnvDTEが必要です。ここで、だから、

(...私のバケツに穴があります)私の質問です:通常のWPFアプリケーションで

は、どのように私は現在のインスタンスEnvDTEのを得ることができますか?

注:私はEnvDTEの古いインスタンスを探していません。私は(私は一度のVisual Studioの3-4のインスタンスを実行してください。)私の現在のVisual Studioインスタンスのいずれかが必要

+0

はあなたのWPFのコードは完全にここで別々のプロセスであり、またはWPFのコードはまだビジュアル内部で実行されています他の仕組みを使ってスタジオ? –

+0

@jason - ちょうど普通のwpfアプリ。私は設計時にそれを実行する予定です。しかし、私は実行時に(たとえばOnClickイベントで)動作する例に満足しています。 (新しいwpfアプリケーションを作成し、ウィンドウ上のボタンをドラッグしてダブルクリックしてください) – Vaccano

+1

GetActiveObjectを適切なモニカを使用して、必要なVSインスタンスに呼び出す必要があります。これは、必要な情報の種類ですか:http://msdn.microsoft.com/en-us/library/ms228755.aspx? –

答えて

8

この質問は、あなたが探している先の答えを持っています。ここ

Get the reference of the DTE2 object in Visual C# 2010

具体

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

コードは次のとおり

Usings:

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; 
} 

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

+0

こんにちはVaccano、私はちょうど私のポストにあなたのコメントを読んだ、と私は私の答えはあなたを助けてくれてうれしい! – Dennis

0

私たちは、これが正常にこのコードを使用して行っている:

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

それはしかし完璧ではありません - - Visual Studioのインスタンスが1つだけ実行されている必要があります(複数のインスタンスが存在する場合は、そのうちの1つを返しますが、どちらのインスタンスを制御することはできません)。

+0

撮影 - ちょうど再読みあなたの投稿と複数のインスタンスについて最後の部分を見て、特定のものを必要としました。申し訳ありません - 私はそれのために何も持っていません。 – JMarsch

3

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

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

あなたはToolWindowクラス自体implements IServiceProvider、例えば、(それがToolWindowPaneから継承)ツールウィンドウでVsPackageを作成している場合。 このような場合、WPerコントロールで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) 
+0

悲しいかな、私が言ったように、これは「普通のWPFアプリ」のためのものです。ツールやパッケージを実装するものはありません。 – Vaccano

+0

@VaccanoスタンドアロンWPFアプリケーションを実行している場合は、** EnvDTEインスタンスを選択したいと思うものに基づいて** EnvDTEの古い/新しいインスタンスは何ですか?古い/新しいバージョンのEnvDTEですか、あるいは時系列的に呼び出された最後のVisual Studioインスタンスを指していますか? –

+0

どこが混乱しているのか分かります。私はWPFアプリケーション(通常のWPFアプリケーション)にいくつかのデザインタイムエレメントを追加したいので、これをやっています。しかし、私はテンプレートやアドインを持っていません。ちょうど普通のWPFアプリ。クイックホーンの答えは私のために働いてしまった。 – Vaccano

0

an answerこのような質問に投稿しました:Get the reference of the DTE2 object in Visual C# 2010

私のアプローチは、実行可能なアセンブリパスをDTE2.Solution.FullNameと比較して、Quickhornsの答えと同じROT列挙を使用した後で、正しいVisual Studioインスタンスを見つけることです。これを行うに興味がある人のための

0

のF#で、ほとんど完全な変換が(現在linqpadで実行するように設定)ここにある:

open System; 
open System.Runtime.InteropServices; 
open System.Runtime.InteropServices.ComTypes; 
open EnvDTE; 
open System.Diagnostics; 
//http://stackoverflow.com/questions/10864595/getting-the-current-envdte-or-iserviceprovider-when-not-coding-an-addin 

//http://stackoverflow.com/questions/6558789/how-to-convert-out-ref-extern-parameters-to-f 
//http://stackoverflow.com/questions/1689460/f-syntax-for-p-invoke-signature-using-marshalas 

[<System.Runtime.InteropServices.DllImport("ole32.dll")>] 
extern int CreateBindCtx(System.IntPtr inRef, IBindCtx& outParentRef); 
[<System.Runtime.InteropServices.DllImport("ole32.dll")>] 
extern int GetRunningObjectTable(System.IntPtr inRef, IRunningObjectTable& outParentRef); 
//let dte = System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.12.0") :?> EnvDTE80.DTE2 
let comName="VisualStudio.DTE.12.0" 
let rotEntry = "!"+comName 
//let mutable rot:IRunningObjectTable =null 

let rot= 
    let mutable result:IRunningObjectTable = null 
    GetRunningObjectTable(nativeint 0, &result) |> ignore 
    result 


let mutable enumMoniker:IEnumMoniker = null 
rot.EnumRunning (&enumMoniker) 
enumMoniker.Reset() |> ignore 
let mutable fetched = IntPtr.Zero 
let mutable moniker:IMoniker[] = Array.zeroCreate 1 //http://msdn.microsoft.com/en-us/library/dd233214.aspx 

let matches = seq { 
    while enumMoniker.Next(1, moniker, fetched) = 0 do 
     "looping" |> Dump 
     let mutable bindCtx:IBindCtx = null 
     CreateBindCtx(nativeint 0, &bindCtx) |> ignore 
     let mutable displayName:string = null 
     moniker.[0].GetDisplayName(bindCtx,null, &displayName) 
     displayName |> Dump 
     if displayName.StartsWith(rotEntry) then 
      let mutable comObject = null 
      rot.GetObject(moniker.[0], &comObject) |> ignore 
      let dte = comObject:?>EnvDTE80.DTE2 
      yield displayName,bindCtx,comObject,dte.FullName, dte 
} 
matches |> Dump 
関連する問題