14

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

ここで提供されている例を powershellにトランスコードしようとしていますが、エラーが発生しています。

私がテストしているPowerShellコードは次のとおりです。

まず、DTE アセンブリを参照する小さな関数を実行します。

$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 型にキャストするにはどうすればよいでしょうか。

4

3 に答える 3

17

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 インスタンスの解放について心配する必要はないと思います。

于 2013-03-05T00:03:26.070 に答える