Sto cercando di utilizzare PowerShell per automatizzare il processo di creazione di una soluzione a più livelli basata su una configurazione di seed (si pensi al file EDMX o DbContext). Voglio essere in grado di aprire una soluzione di scheletro, ottenere l'istanza attiva e popolare i file di progetto con il codice generato automaticamente.Come utilizzare DTE in PowerShell?
Sto provando a transcodificare l'esempio fornito here a powershell, tuttavia, sto ricevendo errori.
Ecco il codice PowerShell sto testando:
In primo luogo, eseguo una piccola funzione per fare riferimento alle assemblee 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
Poi, cerco di creare un oggetto per fare riferimento al risultato della chiamata [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
o:
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
Infine, questo non funziona neanche:
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
Quindi, la mia domanda è, come si usa DTE da PowerShell? Più specificamente, come si esegue il cast chiamando GetActiveObject per digitare EnvDTE.DTE2?
Credo che la classe [TypeWrapper] (http://nuget.codeplex.com/SourceControl/changeset/view/46278ab10d9a#src/VsConsole/PowerShellHost/Utils/TypeWrapper.cs) di NuGet funzioni attorno a questo stesso problema. (** Attenzione: ** codice con licenza Apache di proprietà della Outercurve Foundation) – bricelam
Questo è un ottimo suggerimento e, molte informazioni sono state fornite esaminando questo codice. Tuttavia, sembra di aver trovato un'alternativa semplice. Come si vedrà nella mia risposta di follow-up, PowerShell gestisce il processo in modo leggermente diverso, quindi la trasmissione come descritto su MSDN non è richiesta. –
Se si sta utilizzando la console del gestore pacchetti in VS, l'EnvDTE dell'istanza corrente è già fornita dalla variabile '$ dte'. – StingyJack