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 的调用返回一个 COM 对象,可以直接在 PowerShell 中使用。执行 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")

我不是 100% 确定,因为我不太了解 PowerShell 或 COM,但我认为您不必担心释放 COM 实例。

于 2013-03-05T00:03:26.070 回答
2

对于 VS 2017,如下所示:

$dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE.15.0")
于 2018-11-20T15:07:46.717 回答
1

运行 Visual Studio 2019,我已经能够使用“VisualStudio.DTE”COM 接口(没有版本)启动调试器:

#Get the ProcessID from an AppPool's worker process: 
[int] $ProcessId = ([xml] (& "$env:SystemRoot\system32\inetsrv\appcmd.exe" list wp /xml /apppool.name:"DefaultAppPool")).appcmd.WP."WP.NAME"

# Start the debugger, attached to that ProcessID
[Runtime.InteropServices.Marshal]::GetActiveObject('VisualStudio.DTE').Debugger.LocalProcesses | 
       ? {$_.ProcessID -eq $ProcessId} | %{$_.Attach()}

以前需要指定版本。

于 2020-06-26T21:53:35.477 回答