Tengo un ensamblado .NET (un dll) que es una API para respaldar el software que usamos aquí. Contiene algunas propiedades y métodos que me gustaría aprovechar en mis scripts de Powershell. Sin embargo, me encuentro con muchos problemas al cargar primero el ensamblaje y luego usar cualquiera de los tipos una vez que se carga el ensamblaje.
La ruta completa del archivo es:
C:\rnd\CloudBerry.Backup.API.dll
En Powershell uso:
$dllpath = "C:\rnd\CloudBerry.Backup.API.dll"
Add-Type -Path $dllpath
Me sale el error a continuación:
Add-Type : Unable to load one or more of the requested types. Retrieve the
LoaderExceptions property for more information.
At line:1 char:9
+ Add-Type <<<< -Path $dllpath
+ CategoryInfo : NotSpecified: (:) [Add-Type], ReflectionTypeLoadException
+ FullyQualifiedErrorId : System.Reflection.ReflectionTypeLoadException,Microsoft.PowerShell.Commands.AddTypeComma
ndAdd-Type : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Usar el mismo cmdlet en otro ensamblado .NET, DotNetZip , que tiene ejemplos del uso de la misma funcionalidad en el sitio, tampoco funciona para mí.
Eventualmente encuentro que aparentemente soy capaz de cargar el ensamblaje usando la reflexión:
[System.Reflection.Assembly]::LoadFrom($dllpath)
Aunque no entiendo la diferencia entre los métodos Load, LoadFrom o LoadFile, ese último método parece funcionar.
Sin embargo, todavía parece que no puedo crear instancias o usar objetos. Cada vez que lo intento, recibo errores que describen que Powershell no puede encontrar ninguno de los tipos públicos.
Sé que las clases están ahí:
$asm = [System.Reflection.Assembly]::LoadFrom($dllpath)
$cbbtypes = $asm.GetExportedTypes()
$cbbtypes | Get-Member -Static
---- inicio del extracto ----
TypeName: CloudBerryLab.Backup.API.BackupProvider
Name MemberType Definition
---- ---------- ----------
PlanChanged Event System.EventHandler`1[CloudBerryLab.Backup.API.Utils.ChangedEventArgs] PlanChanged(Sy...
PlanRemoved Event System.EventHandler`1[CloudBerryLab.Backup.API.Utils.PlanRemoveEventArgs] PlanRemoved...
CalculateFolderSize Method static long CalculateFolderSize()
Equals Method static bool Equals(System.Object objA, System.Object objB)
GetAccounts Method static CloudBerryLab.Backup.API.Account[], CloudBerry.Backup.API, Version=1.0.0.1, Cu...
GetBackupPlans Method static CloudBerryLab.Backup.API.BackupPlan[], CloudBerry.Backup.API, Version=1.0.0.1,...
ReferenceEquals Method static bool ReferenceEquals(System.Object objA, System.Object objB)
SetProfilePath Method static System.Void SetProfilePath(string profilePath)
---- fin del extracto ----
Intentar usar métodos estáticos falla, ¡no sé por qué!
[CloudBerryLab.Backup.API.BackupProvider]::GetAccounts()
Unable to find type [CloudBerryLab.Backup.API.BackupProvider]: make sure that the assembly containing this type is load
ed.
At line:1 char:42
+ [CloudBerryLab.Backup.API.BackupProvider] <<<< ::GetAccounts()
+ CategoryInfo : InvalidOperation: (CloudBerryLab.Backup.API.BackupProvider:String) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
Cualquier orientación apreciada!
fuente
Encontré este enlace: http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html
Él dice: ".LoadWithPartialName" ha quedado en desuso. Por lo tanto, en lugar de continuar implementando Add-Type con ese método, utiliza una tabla interna estática para traducir el "nombre parcial" a un "nombre completo". En el ejemplo dado en la pregunta,
CloudBerry.Backup.API.dll
no tiene una entrada en la tabla interna de PowerShell, razón por la cual[System.Reflection.Assembly]::LoadFrom($dllpath)
funciona. No está usando la tabla para buscar un nombre parcial.fuente
Algunos de los métodos anteriores no funcionaron para mí o no estaban claros.
Esto es lo que uso para envolver llamadas -AddPath y capturar LoaderExceptions:
Referencia
https://social.technet.microsoft.com/Forums/sharepoint/en-US/dff8487f-69af-4b64-ab83-13d58a55c523/addtype-inheritance-loaderexceptions
fuente
Usé la siguiente configuración para cargar un control csharp personalizado en powershell. Permite que el control se personalice y se utilice desde powershell.
aquí está el enlace del blog
http://justcode.ca/wp/?p=435
y aquí está el enlace del proyecto de código con la fuente
http://www.codeproject.com/Articles/311705/Custom-CSharp-Control-for-Powershell
fuente
El
LoaderExceptions
están escondidos en el interior del registro de error. Si el error add-type fue el último en la lista de errores, use$Error[0].InnerException.LoaderExceptions
para mostrar los errores. Lo más probable es que su biblioteca dependa de otra que no se haya cargado. PuedeAdd-Type
cada uno, o simplemente hacer una lista y usar el-ReferencedAssemblies
argumento paraAdd-Type
.fuente
Creo que a estas alturas PODRÍAS haber encontrado una respuesta a este fenómeno. Me encontré con esta publicación después de encontrar el mismo problema ... Pude cargar el ensamblaje y ver los tipos contenidos en el ensamblaje, pero no pude instanciar una instancia de él desde una clase estática. ¿Fue EFTIDY? Tidy, EFTidyNet.TidyNet.Options o qué? Ooooo Weeee ... Problemas ... problemas ... podría ser cualquier cosa. Y mirar a través de los métodos y tipos estáticos de la DLL no reveló nada prometedor. Ahora me estaba deprimiendo. Lo tenía trabajando en un programa C # compilado, pero para mi uso quería que se ejecutara en un lenguaje interpelado ... PowerShell.
Encontré mi solución, y todavía se está probando, pero estoy eufórico y quería compartir esto. Construya una pequeña aplicación console.exe ejerciendo el func que me interesaba y luego véala en algo que la descompilara o mostrara el código IL. ¡Utilicé el reflector de Red-Gate y el complemento del generador de lenguaje powershell y Wallah! ¡mostró cuál era la cadena de constructor adecuada! :-) Intentalo. y espero que funcione para quien enfrenta este problema.
fuente