La mayoría de las personas ya saben que System.Reflection.Assembly.LoadWithPartialName
está en desuso, pero resulta que Add-Type -AssemblyName Microsoft.VisualBasic
no se comporta mucho mejor queLoadWithPartialName
:
En lugar de intentar analizar su solicitud en el contexto de su sistema, [Add-Type] mira una tabla interna estática para traducir el "nombre parcial" a un "nombre completo".
Si su "nombre parcial" no aparece en su tabla, su script fallará.
Si tiene varias versiones del ensamblaje instaladas en su computadora, no hay un algoritmo inteligente para elegir entre ellas. Obtendrá el que aparezca en su tabla, probablemente el más antiguo y anticuado.
Si las versiones que ha instalado son todas más nuevas que las obsoletas en la tabla, su script fallará.
Add-Type no tiene un analizador inteligente de "nombres parciales" como
.LoadWithPartialNames
.
Lo que Microsoft dice que está en realidad supone que debe hacer es algo como esto:
Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
O, si conoce el camino, algo como esto:
Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'
Ese nombre largo dado para el ensamblado se conoce como el nombre seguro , que es exclusivo de la versión y el ensamblado, y también a veces se conoce como el nombre completo.
Pero esto deja un par de preguntas sin respuesta:
¿Cómo determino el nombre seguro de lo que realmente se está cargando en mi sistema con un nombre parcial dado?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
Estos también deberían funcionar:
Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Si quiero que mi script siempre use una versión específica de un .dll pero no puedo estar seguro de dónde está instalado, ¿cómo puedo determinar cuál es el nombre seguro del .dll?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
O:
Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Si conozco el nombre seguro, ¿cómo determino la ruta .dll?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
Y, en una línea similar, si sé el nombre del tipo de lo que estoy usando, ¿cómo sé de qué conjunto proviene?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
¿Cómo veo qué conjuntos están disponibles?
Sugiero el módulo GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
funciona bastante bien
- ¿Cómo puedo ver la lista que
Add-Type
usa?
Esto es un poco más complejo. Puedo describir cómo acceder a él para cualquier versión de PowerShell con un reflector .Net (consulte la actualización a continuación para PowerShell Core 6.0).
Primero, descubra de qué biblioteca Add-Type
proviene:
Get-Command -Name Add-Type | Select-Object -Property DLL
Abra la DLL resultante con su reflector. He usado ILSpy para esto porque es FLOSS, pero cualquier reflector C # debería funcionar. Abra esa biblioteca y mire adentro Microsoft.Powershell.Commands.Utility
. Debajo Microsoft.Powershell.Commands
, debería haber AddTypeCommand
.
En el listado de código para eso, hay una clase privada, InitializeStrongNameDictionary()
. Eso enumera el diccionario que asigna los nombres cortos a los nombres fuertes. Hay casi 750 entradas en la biblioteca que he visto.
Actualización: ahora que PowerShell Core 6.0 es de código abierto. Para esa versión, puede omitir los pasos anteriores y ver el código directamente en línea en su repositorio de GitHub . Sin embargo, no puedo garantizar que ese código coincida con cualquier otra versión de PowerShell.