Ich versuche, PowerShell zu verwenden, um den Prozess der Erstellung einer n-Tier-Lösung basierend auf einer Seed-Konfiguration (EDMX-Datei oder DbContext) zu automatisieren. Ich möchte in der Lage sein, eine Skelettlösung zu öffnen, die aktive Instanz abzurufen und Projektdateien mit automatisch generiertem Code zu füllen.Wie wird DTE in PowerShell verwendet?
Ich versuche, das Beispiel here Powershell zu transcodieren, bekomme ich jedoch Fehler.
Hier ist die Powershell-Code-I-Tests sind:
Zuerst fahre ich eine kleine Funktion, die DTE-Baugruppen zu verweisen.
$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
Dann versuche ich, ein Objekt zu erstellen, das Ergebnis der [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
oder referenzieren Aufruf:
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
Schließlich funktioniert das nicht entweder:
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
Also, meine Frage ist, wie verwenden Sie DTE von PowerShell? Genauer gesagt, wie wird das Ergebnis des Aufrufs von GetActiveObject in EnvDTE.DTE2 umgewandelt?
Ich glaube, NuGet's [TypeWrapper] (http://nuget.codeplex.com/SourceControl/changeset/view/46278ab10d9a#src/VsConsole/PowerShellHost/Utils/TypeWrapper.cs) -Klasse funktioniert um das gleiche Problem. (** Achtung: ** Apache-lizenzierter Code im Besitz der Outercurve Foundation) – bricelam
Dies ist ein großartiger Vorschlag, und durch die Überprüfung dieses Codes wurden viele Einsichten geliefert. Es scheint jedoch, dass ich eine einfache Alternative gefunden habe. Wie Sie in meiner Antwort sehen werden, behandelt PowerShell den Prozess ein wenig anders. Daher ist Casting wie in MSDN beschrieben nicht erforderlich. –
Wenn Sie die Paketmanagerkonsole in VS verwenden, wird das EnvDTE der aktuellen Instanz bereits von der Variablen $ dte bereitgestellt. – StingyJack