2013-03-04 89 views
9

我想使用PowerShell來自動創建基於種子(認爲EDMX文件或DbContext)配置的n層解決方案的過程。我希望能夠打開框架解決方案,獲取活動實例,並使用自動生成的代碼填充項目文件。如何在PowerShell中使用DTE?

我試圖將提供的示例代碼here轉換爲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的結果?

+0

我相信NuGet的[TypeWrapper](http://nuget.codeplex.com/SourceControl/changeset/view/46278ab10d9a#src/VsConsole/PowerShellHost/Utils/TypeWrapper.cs)類可以解決這個問題。 (**警告:**由Outercurve Foundation擁有的Apache許可代碼) – bricelam 2013-03-04 21:11:44

+0

這是一個很好的建議,並且通過查看此代碼提供了許多洞察。但是,似乎我找到了一個簡單的選擇。正如您在後續答案中所看到的,PowerShell處理該過程的方式有點不同,因此,不需要按照MSDN上的說明進行投射。 – 2013-03-04 23:52:00

+0

如果您在VS中使用包管理器控制檯,則當前實例的EnvDTE已由$ dte變量提供。 – StingyJack 2017-04-29 13:43:51

回答

13

我在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實例。

+0

這是[this](http://www.computerperformance.co.uk/powershell/powershell_com.htm)文章,它提供了有助於找到答案的線索。 – 2013-03-05 00:08:46

+0

「執行LoadDTELibs之後」 - 您是如何執行此操作的? – Rhyous 2016-02-29 16:20:40