A maioria das pessoas sabe até agora que System.Reflection.Assembly.LoadWithPartialName
está obsoleta, mas acontece queAdd-Type -AssemblyName Microsoft.VisualBasic
não se comporta muito melhor do queLoadWithPartialName
:
Em vez de tentar analisar sua solicitação no contexto do seu sistema, o [Add-Type] analisa uma tabela interna estática para converter o "nome parcial" em um "nome completo".
Se o seu "nome parcial" não aparecer na tabela, o script falhará.
Se você tiver várias versões do assembly instaladas no seu computador, não há algoritmo inteligente para escolher entre elas. Você receberá o que aparecer na tabela deles, provavelmente o mais antigo e desatualizado.
Se as versões instaladas forem todas mais novas que as obsoletas da tabela, seu script falhará.
Add-Type não possui um analisador inteligente de "nomes parciais", como
.LoadWithPartialNames
.
O que a Microsoft diz que você realmente deve fazer é algo como isto:
Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Ou, se você conhece o caminho, algo como isto:
Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'
Esse nome longo dado para a montagem é conhecido como nome forte , que é exclusivo da versão e do assembly, e também é conhecido como nome completo.
Mas isso deixa algumas perguntas sem resposta:
Como determino o nome forte do que realmente está sendo carregado no meu sistema com um nome parcial fornecido?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
Estes também devem funcionar:
Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Se quiser que meu script sempre use uma versão específica de uma .dll, mas não tenha certeza de onde está instalado, como determino qual é o nome forte da .dll?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
Ou:
Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Se eu souber o nome forte, como determino o caminho .dll?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
E, de maneira semelhante, se eu sei o nome do tipo do que estou usando, como sei de que montagem ele está vindo?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
Como vejo quais montagens estão disponíveis?
Sugiro o módulo GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
funciona muito bem.
- Como posso ver a lista que
Add-Type
usa?
Isso é um pouco mais complexo. Posso descrever como acessá-lo para qualquer versão do PowerShell com um refletor .Net (consulte a atualização abaixo para o PowerShell Core 6.0).
Primeiro, descubra de que biblioteca Add-Type
vem:
Get-Command -Name Add-Type | Select-Object -Property DLL
Abra a DLL resultante com seu refletor. Eu usei o ILSpy para isso porque é FLOSS, mas qualquer refletor em C # deve funcionar. Abra essa biblioteca e veja Microsoft.Powershell.Commands.Utility
. Abaixo Microsoft.Powershell.Commands
, deve haver AddTypeCommand
.
Na lista de códigos para isso, há uma classe privada InitializeStrongNameDictionary()
,. Isso lista o dicionário que mapeia os nomes abreviados para os nomes fortes. Há quase 750 entradas na biblioteca que eu olhei.
Atualização: Agora que o PowerShell Core 6.0 é de código aberto. Para essa versão, você pode pular as etapas acima e ver o código diretamente online no repositório do GitHub . Não posso garantir que esse código corresponda a qualquer outra versão do PowerShell, no entanto.