La maggior parte delle persone sa ormai che System.Reflection.Assembly.LoadWithPartialName
è deprecata, ma si scopre che Add-Type -AssemblyName Microsoft.VisualBasic
non si comporta molto meglio diLoadWithPartialName
:
Invece di tentare di analizzare la tua richiesta nel contesto del tuo sistema, [Add-Type] esamina una tabella interna statica per tradurre il "nome parziale" in un "nome completo".
Se il tuo "nome parziale" non appare nella loro tabella, lo script non funzionerà.
Se sul computer sono installate più versioni dell'assembly, non esiste un algoritmo intelligente tra cui scegliere. Stai per ottenere quello che appare nella loro tabella, probabilmente il più vecchio, obsoleto.
Se le versioni installate sono tutte più recenti di quelle obsolete nella tabella, lo script non funzionerà.
Add-Type non ha un parser intelligente di "nomi parziali" come
.LoadWithPartialNames
.
Quello che Microsoft dice che dovresti effettivamente fare è qualcosa del genere:
Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Oppure, se conosci il percorso, qualcosa del genere:
Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'
Quel lungo nome fornito per l'assemblaggio è noto come il nome sicuro , che è sia unico per la versione che per l'assemblaggio, ed è talvolta noto anche come il nome completo.
Ma questo lascia un paio di domande senza risposta:
Come posso determinare il nome sicuro di ciò che viene effettivamente caricato sul mio sistema con un determinato nome parziale?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
Questi dovrebbero anche funzionare:
Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Se voglio che il mio script usi sempre una versione specifica di un .dll ma non posso essere sicuro di dove sia installato, come posso determinare quale sia il nome sicuro del .dll?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
O:
Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Se conosco il nome sicuro, come posso determinare il percorso .dll?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
E, allo stesso modo, se conosco il nome del tipo di ciò che sto usando, come faccio a sapere da quale assembly proviene?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
Come posso vedere quali assembly sono disponibili?
Suggerisco il modulo GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
funziona abbastanza bene.
- Come posso vedere l'elenco che
Add-Type
utilizza?
Questo è un po 'più complesso. Posso descrivere come accedervi per qualsiasi versione di PowerShell con un riflettore .Net (vedere l'aggiornamento di seguito per PowerShell Core 6.0).
Innanzitutto, scopri da quale libreria Add-Type
proviene:
Get-Command -Name Add-Type | Select-Object -Property DLL
Apri la DLL risultante con il tuo riflettore. Ho usato ILSpy per questo perché è FLOSS, ma qualsiasi riflettore C # dovrebbe funzionare. Apri quella libreria e guarda dentro Microsoft.Powershell.Commands.Utility
. Sotto Microsoft.Powershell.Commands
, ci dovrebbe essere AddTypeCommand
.
Nel listato di codice per questo, c'è una classe privata, InitializeStrongNameDictionary()
. Questo elenca il dizionario che associa i nomi brevi ai nomi forti. Ci sono quasi 750 voci nella biblioteca che ho visto.
Aggiornamento: ora che PowerShell Core 6.0 è open source. Per quella versione, puoi saltare i passaggi precedenti e vedere il codice direttamente online nel loro repository GitHub . Tuttavia, non posso garantire che quel codice corrisponda a qualsiasi altra versione di PowerShell.