Como adicionar corretamente os assemblies do .NET à sessão do Powershell?

20

Eu tenho um assembly .NET (uma dll) que é uma API para o software de backup que usamos aqui. Ele contém algumas propriedades e métodos que eu gostaria de aproveitar em meu (s) script (s) do Powershell. No entanto, estou com muitos problemas ao carregar primeiro o conjunto e usar qualquer um dos tipos depois que o conjunto é carregado.

O caminho completo do arquivo é:

C:\rnd\CloudBerry.Backup.API.dll

Em 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.

Usando o mesmo cmdlet em outro assembly .NET, o DotNetZip , que tem exemplos de uso da mesma funcionalidade no site, também não trabalhe para mim.

Eu finalmente descobri que aparentemente 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, parece que ainda não consigo 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, não sei 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

Qualquer orientação apreciada !!

    
por amandion 05.12.2012 / 05:24

6 respostas

13

Você pode cercar o Add-Type com um try catch e imprimir a propriedade LoaderExceptions, como o erro está dizendo. Pode fornecer uma exceção com uma mensagem de erro mais detalhada.

try
{
    Add-Type -Path "C:\rnd\CloudBerry.Backup.API.dll"
}
catch
{
    $_.LoaderExceptions | %
    {
        Write-Error $_.Message
    }
}
    
por 26.06.2013 / 21:45
2

Eu encontrei este link: link

Ele diz que ".LoadWithPartialName" foi descontinuado. Portanto, em vez de continuar a implementar 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 tem 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.

    
por 22.09.2015 / 20:38
1

Alguns dos métodos acima não funcionaram para mim ou não estavam claros.

Veja o que eu uso para finalizar chamadas -AddPath e capturar LoaderExceptions:

try
{
   Add-Type -Path "C:\path\to.dll"
}
catch [System.Reflection.ReflectionTypeLoadException]
{
   Write-Host "Message: $($_.Exception.Message)"
   Write-Host "StackTrace: $($_.Exception.StackTrace)"
   Write-Host "LoaderExceptions: $($_.Exception.LoaderExceptions)"
}

Referência
link

    
por 12.02.2018 / 14:12
0

Eu usei a seguinte configuração para carregar um controle personalizado de csharp no powershell. Permite que o controle seja personalizado e utilizado dentro do powershell.

aqui está o link do blog

link

e aqui está o link do código de projeto com a fonte

link

    
por 10.03.2013 / 03:35
0

O LoaderExceptions está oculto dentro do registro de erro. Se o erro de tipo de acréscimo for o último da lista de erros, use $Error[0].InnerException.LoaderExceptions para mostrar os erros. Muito provavelmente, sua biblioteca depende de outra que não tenha sido carregada. Você pode Add-Type cada um, ou apenas fazer uma lista e usar o argumento -ReferencedAssemblies para Add-Type .

    
por 05.09.2013 / 01:34
-1

Acho que agora você MIGHT encontrou uma resposta para esse fenômeno. Eu corri neste post depois de encontrar o mesmo problema ... Eu poderia carregar o assembly e ver os tipos contidos na montagem, mas não foi possível instanciar uma instância dele de uma classe estática. Foi EFTIDY. Tidy, EFTidyNet.TidyNet.Options ou o que? Ooooo Weeee ... Problemas ... problemas ... pode ser qualquer coisa. E olhando através dos métodos estáticos e tipos da DLL não revelou nada promissor. Agora eu estava ficando deprimido. Eu tive que trabalhar em um programa C # compilado, mas para o meu uso eu queria tê-lo funcionando em uma linguagem interpeted ... powershell.

Minha solução eu encontrei e ainda está sendo comprovada, mas estou entusiasmada e queria compartilhar isso. Crie um pequeno aplicativo console.exe exercitando o func que eu estava interessado e, em seguida, visualizá-lo em algo que iria descompilar ou mostrar o código IL. Eu usei o refletor de Red-Gate e o suplemento do gerador de linguagem do PowerShell e Wallah! mostrava qual era a string adequada do construtor! :-) Tente. e espero que funcione para quem se deparar com esse problema.

    
por 05.08.2015 / 04:51