【VisualStudio】アドイン以外からソリューション情報を参照する方法

たまにはリリースのお知らせ以外の更新を。


VisualStudioでアドインプロジェクトを作成すると
起点となるメソッドで引数からDTE2という型のオブジェクトを取得することができ、
そこから起動中のVisualStudio、ソリューションの情報を参照、取り扱うことができます。


/// アドインを実装するためのオブジェクトです。
///
public class Connect : IDTExtensibility2 {
(省略)
/// IDTExtensibility2 インターフェイスの OnConnection メソッドを実装します。アドインが読み込まれる際に通知を受けます。
/// ホスト アプリケーションのルート オブジェクトです。
/// アドインの読み込み状態を説明します。
/// このアドインを表すオブジェクトです。
///
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
// ↓このオブジェクトからVisualStudio、ソリューション等の情報を参照、操作できる
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
}
(省略)


このDTE2オブジェクトをアドイン以外(通常のコンソールプログラム等)のプログラムから
取得する方法
をメモ代わりに書いてみます。
実装例のコードはVisualStudio2010で作成、確認しています。

  1. 環境の整備
    プロジェクトの「参照設定」に「EnvDTE」「EnvDTE80」を追加する
    ※アドインが使えるエディションのVisualStudioをインストールしていない環境では未確認
  2. コーディング
    下記のようにソースコードを書く


// DTE2オブジェクト取得
var vs = (EnvDTE80.DTE2)System.Activator.CreateInstance(
System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0"));
// ソリューションファイルを開く
vs.Solution.Open(@"C:\hoge\Seasar.sln");
System.Console.WriteLine(vs.Solution.FullName);

// 読み込んだソリューション下のプロジェクト名を出力
foreach (Project p in vs.Solution.Projects) {
System.Console.WriteLine(p.FullName);
}

○実行結果

C:\hoge\Seasar.sln
C:\hoge\Seasar\Seasar.csproj
C:\hoge\Seasar.Tests\Seasar.Tests.csproj
C:\hoge\Seasar.Unit\Seasar.Unit.csproj
C:\hoge\Seasar.DynamicProxy\Seasar.DynamicProxy.csproj
C:\hoge\Seasar.Windows\Seasar.Windows.csproj
C:\hoge\Seasar.Quill\Seasar.Quill.csproj
C:\hoge\Seasar.Quill.Examples\Seasar.Quill.Examples.csproj
C:\hoge\Seasar.Dao\Seasar.Dao.csproj
C:\hoge\Seasar.Dxo\Seasar.Dxo.csproj
【注意点】
DTE2オブジェクトを生成する際に渡している「"VisualStudio.DTE.10.0"」の
数字部分には扱いたいVisualStudioのバージョン番号が入ります。
VisualStudio2010なら「10.0」、2008なら「9.0」となります。
このバージョン番号と実際に読み込んだソリューションファイルのバージョンが
合っていない場合、COMExceptionが発生します。
○例

// DTE2オブジェクト取得(バージョン番号は9.0(VisualStudio2008用))
vs = (DTE2)System.Activator.CreateInstance(
System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0"));
// VisualStudio2010で作成したソリューションファイルを開く
vs.Solution.Open(TEST_SOL_PATH);
System.Console.WriteLine(vs.Solution.FullName);
○実行結果

System.Runtime.InteropServices.COMException (0x80004004): 操作は中断されました (HRESULT からの例外: 0x80004004 (E_ABORT))
場所 EnvDTE.SolutionClass.Open(String FileName)


対処例として、とりあえず思いつくのはソリューションファイル内に書かれている
書式バージョン番号(注:何故かVisualStudioのバージョン+1)を利用する方法です。


○ソリューションファイルの中身(先頭行に書式のバージョン番号が記述してある)

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Seasar", "Seasar\Seasar.csproj", "{7224C3B3-2C10-4AC5-A118-56558ED4C3C9}"
EndProject
(省略)
○実装例

const string ENV_DTE_OBJ_NAME = "VisualStudio.DTE.";
var version = GetVersion(solutionPath); // ソリューションファイルを読んでバージョン番号を取り出す
var vs = (DTE2)Activator.CreateInstance(Type.GetTypeFromProgID(ENV_DTE_OBJ_NAME + version));