2013-03-04 8 views
9

Próbuję użyć PowerShell, aby zautomatyzować proces tworzenia rozwiązania n-warstwowego opartego na konfiguracji typu seed (myślę, że plik EDMX lub DbContext). Chcę móc otworzyć szkielet, uzyskać aktywną instancję i zapełnić pliki projektu automatycznie wygenerowanym kodem.Jak korzystać z DTE w PowerShell?

Próbuję transkodować przykład pod warunkiem, here do powershell, jednak dostaję błędy.

Oto kod PowerShell Mam testowanie:

Najpierw wykonać trochę funkcji odwołać zespoły 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 

Następnie próbuję utworzyć obiekt odniesienia wynik wywołania [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 

czyli

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 

Wreszcie, to nie działa albo:

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 

Tak, moje pytanie brzmi: w jaki sposób korzystasz z DTE z PowerShell? Dokładniej, w jaki sposób rzucić wynik wywoływania GetActiveObject, aby wpisać EnvDTE.DTE2?

+0

Wierzę, że klasa NuGet [TypeWrapper] (http://nuget.codeplex.com/SourceControl/changeset/view/46278ab10d9a#src/VsConsole/PowerShellHost/Utils/TypeWrapper.cs) działa w podobny sposób. (** Uwaga: ** kod licencjonowany przez Apache, należący do fundacji Outercurve). – bricelam

+0

To jest świetna propozycja, i wiele informacji uzyskano, przeglądając ten kod. Wydaje się jednak, że znalazłem prostą alternatywę. Jak zobaczysz w odpowiedzi na moje pytanie, PowerShell obsługuje proces nieco inaczej, więc przesyłanie zgodnie z opisem na MSDN nie jest wymagane. –

+0

Jeśli używasz konsoli menedżera pakietów w VS, EnvDTE obecnej instancji jest już dostarczony przez zmienną '$ dte'. – StingyJack

Odpowiedz

13

Znalazłem prostą odpowiedź, bawiąc się pomysłem w ISE na chwilę.

Zasadniczo wywołanie GetActiveObject zwraca obiekt COM, którego można użyć bezpośrednio w programie PowerShell. Po uruchomieniu LoadDTELibs można uzyskać instancję DTE, wywołując GetActiveObject, a następnie odnieść się bezpośrednio do wyniku.

Więc ...

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

Następnie:

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

nie jestem w 100% pewien, bo nie wiem PowerShell lub COM wszystko dobrze, ale myślę, że ty nie Naprawdę musisz się martwić uwolnieniem instancji COM.

+0

To był [ten] (http://www.computerperformance.co.uk/powershell/powershell_com.htm) artykuł, który dostarczył wskazówek, które były pomocne w znalezieniu odpowiedzi. –

+0

"Po wykonaniu LoadDTELibs" - Jak to zrobiłeś? – Rhyous