Eu tenho um assembly .NET (uma dll) que é uma API para fazer backup do software que usamos aqui. Ele contém algumas propriedades e métodos dos quais gostaria de aproveitar meus scripts do Powershell. No entanto, estou enfrentando muitos problemas ao carregar primeiro o assembly e depois usar qualquer um dos tipos depois que o assembly é carregado.
O caminho completo do arquivo é:
C:\rnd\CloudBerry.Backup.API.dll
No Powershell eu uso:
$dllpath = "C:\rnd\CloudBerry.Backup.API.dll"
Add-Type -Path $dllpath
Eu recebo o erro abaixo:
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 o mesmo cmdlet em outro assembly .NET, DotNetZip , que tem exemplos de uso da mesma funcionalidade no site, também não funciona para mim.
Eventualmente, acho que sou capaz de carregar o assembly usando a reflexão:
[System.Reflection.Assembly]::LoadFrom($dllpath)
Embora eu não entenda a diferença entre os métodos Load, LoadFrom ou LoadFile, esse último método parece funcionar.
No entanto, ainda pareço incapaz de criar instâncias ou usar objetos. Cada vez que tento, recebo erros que descrevem que o Powershell não consegue encontrar nenhum dos tipos públicos.
Eu sei que as aulas estão lá:
$asm = [System.Reflection.Assembly]::LoadFrom($dllpath)
$cbbtypes = $asm.GetExportedTypes()
$cbbtypes | Get-Member -Static
---- início do trecho ----
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)
---- fim do trecho ----
Tentando usar métodos estáticos falham, não sei por que !!!
[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
Qualquer orientação apreciada !!
fonte
Encontrei este link: http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html
Ele diz que ".LoadWithPartialName" foi preterido. Portanto, em vez de continuar implementando o Add-Type com esse método, ele usa uma tabela interna estática para converter o "nome parcial" em um "nome completo". No exemplo dado na pergunta,
CloudBerry.Backup.API.dll
não há uma entrada na tabela interna do PowerShell, e é por isso que[System.Reflection.Assembly]::LoadFrom($dllpath)
funciona. Não está usando a tabela para procurar um nome parcial.fonte
Alguns dos métodos acima não funcionaram para mim ou não eram claros.
Aqui está o que eu uso para agrupar chamadas -AddPath e capturar LoaderExceptions:
Referência
https://social.technet.microsoft.com/Forums/sharepoint/en-US/dff8487f-69af-4b64-ab83-13d58a55c523/addtype-inheritance-loaderexceptions
fonte
Usei a seguinte configuração para carregar um controle csharp personalizado no PowerShell. Ele permite que o controle seja personalizado e utilizado de dentro do PowerShell.
aqui está o link do blog
http://justcode.ca/wp/?p=435
e aqui está o link do codeproject com a fonte
http://www.codeproject.com/Articles/311705/Custom-CSharp-Control-for-Powershell
fonte
Eles
LoaderExceptions
estão ocultos dentro do registro de erro. Se o erro do tipo adição foi o último na lista de erros, use$Error[0].InnerException.LoaderExceptions
para mostrar os erros. Provavelmente, sua biblioteca depende de outra que não foi carregada. Você podeAdd-Type
cada um ou apenas fazer uma lista e usar o-ReferencedAssemblies
argumento paraAdd-Type
.fonte
Eu acho que agora você DEVE ter encontrado uma resposta para esse fenômeno. Fiz essa postagem depois de encontrar o mesmo problema ... Pude carregar o assembly e visualizar os tipos contidos no assembly, mas não consegui instanciar uma instância dele a partir de uma classe estática. Foi EFTIDY. Arrumado, EFTidyNet.TidyNet.Options ou o quê? Ooooo Weeee ... problemas ... problemas ... pode ser qualquer coisa. E analisar os métodos e tipos estáticos da DLL não revelou nada de promissor. Agora eu estava ficando deprimido. Eu o tinha trabalhando em um programa C # compilado, mas, para meu uso, eu queria que ele fosse executado em um idioma interpetado ... PowerShell.
Encontrei minha solução e ainda está sendo comprovada, mas estou feliz e queria compartilhar isso. Crie um pequeno aplicativo console.exe que exerça a função em que eu estava interessado e, em seguida, visualize-o em algo que o descompile ou mostre o código IL. Usei o refletor da Red-Gate e o complemento gerador de linguagem PowerShell e Wallah! mostrou qual era a string de construtor apropriada! :-) Tente. e espero que funcione para quem enfrenta esse problema.
fonte