2013-03-04 12 views
9

シード(EDMXファイルまたはDbContextと考える)設定に基づいてn層ソリューションを作成するプロセスを自動化するためにPowerShellを使用しようとしています。私はスケルトンソリューションをオープンし、アクティブなインスタンスを取得し、プロジェクトファイルに自動生成されたコードを入力できるようにしたいと考えています。PowerShellでDTEを使用するには?

hereの例をpowerershellにトランスコードしようとしていますが、エラーが発生しています。私はDTEアセンブリを参照するために少し機能を実行し、

まず:

は、ここで私がテストしていPowerShellのコードです。

$libs = "envdte.dll", "envdte80.dll", "envdte90.dll", "envdte100.dll" 
function LoadDTELibs { 
    param(
     $path = "\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies" 
    ) 

    Process { 
     $libs | 
      ForEach { 
       $dll = Join-Path "$env:ProgramFiles\$path" $_ 

       if(-not (Test-Path $dll)) { 
        $dll = Join-Path "${env:ProgramFiles(x86)}\$path" $_ 
       } 

       Add-Type -Path $dll -PassThru | Where {$_.IsPublic -and $_.BaseType} | Sort Name 
      } 
    } 
} 


LoadDTELibs 

はその後、私は[System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE.11.0")

PS> $dte = New-Object -ComObject EnvDTE80.DTE2 

New-Object : Retrieving the COM class factory for component with CLSID {00000000-0000-0000-0000-000000000000} failed due to the following error: 80040154 
Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)). 
At line:1 char:8 
+ $dte = New-Object -ComObject EnvDTE80.DTE2 
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : ResourceUnavailable: (:) [New-Object], COMException 
    + FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand 

かを呼び出した結果を参照するためのオブジェクトを作成しよう:

PS> $dte = New-Object EnvDTE80.DTE2 

New-Object : Constructor not found. Cannot find an appropriate constructor for type EnvDTE80.DTE2. 
At line:1 char:8 
+ $dte = New-Object EnvDTE80.DTE2 
+  ~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : ObjectNotFound: (:) [New-Object], PSArgumentException 
    + FullyQualifiedErrorId : CannotFindAppropriateCtor,Microsoft.PowerShell.Commands.NewObjectCommand 

最後に、これは動作しないかん:

PS> [EnvDTE80.DTE2]$dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE.11.0") 

Cannot convert the "System.__ComObject" value of type "System.__ComObject#{04a72314-32e9-48e2-9b87-a63603454f3e}" to type "EnvDTE80.DTE2". 
At line:1 char:1 
+ [EnvDTE80.DTE2]$dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject(... 
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : MetadataError: (:) [], ArgumentTransformationMetadataException 
    + FullyQualifiedErrorId : RuntimeException 

だから、私の質問は、どのようにPowerShellからDTEを使用するのですか?具体的には、GetActiveObjectをEnvDTE.DTE2型に呼び出す結果をどのようにキャストしますか?

+0

NuGetの[TypeWrapper](http://nuget.codeplex.com/SourceControl/changeset/view/46278ab10d9a#src/VsConsole/PowerShellHost/Utils/TypeWrapper.cs)クラスは、この同じ問題を回避します。 (**注意:** Outercurve Foundationが所有するApacheライセンスコード) – bricelam

+0

これは素晴らしい提案であり、このコードを見直すことによって多くの洞察が得られました。しかし、私は単純な選択肢を見つけたようです。フォローアップの答えでわかるように、PowerShellはプロセスを少しずつ処理します。したがって、MSDNで説明したようなキャストは必要ありません。 –

+0

VSでパッケージマネージャコンソールを使用している場合、現在のインスタンスのEnvDTEはすでに '$ dte'変数によって提供されています。 – StingyJack

答えて

13

ISEのアイデアをしばらく試してみると、簡単な答えが見つかりました。

基本的にGetActiveObjectを呼び出すと、PowerShellで直接使用できるCOMオブジェクトが返されます。 LoadDTELibsを実行した後、GetActiveObjectを呼び出してDTEのインスタンスを取得し、その結果を直接参照できます。

だから... ...その後

PS> $dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE.11.0") 

PS> $dte.solution.Create("D:\Testing", "Acme.sln") 
PS> $dte.solution.SaveAs("D:\Testing\Acme.sln") 

私はすべてのこともPowerShellのか、COMを知らないが、私はあなたドンと思うので、私は、100%わからないんだけどCOMインスタンスを解放することについて本当に心配する必要はありません。

+0

答えを見つけるのに役立つ手がかりを提供したのは[this](http://www.computerperformance.co.uk/powershell/powershell_com.htm)の記事でした。 –

+0

"LoadDTELibsを実行した後" - どのように実行しましたか? – Rhyous

関連する問題