Come aggiungere correttamente gli assembly .NET alla sessione Powershell?


24

Ho un assembly .NET (una dll) che è un'API per il software di backup che utilizziamo qui. Contiene alcune proprietà e metodi che vorrei sfruttare nei miei script Powershell. Tuttavia, sto riscontrando molti problemi con il caricamento dapprima dell'assemblaggio, quindi utilizzando uno dei tipi una volta caricato l'assemblaggio.

Il percorso completo del file è:

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

In Powershell utilizzo:

$dllpath = "C:\rnd\CloudBerry.Backup.API.dll"
Add-Type -Path $dllpath

Ricevo l'errore di seguito:

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.

Utilizzando lo stesso cmdlet su un altro assembly .NET, anche DotNetZip , che contiene esempi di utilizzo della stessa funzionalità sul sito, non funziona per me.

Alla fine trovo che sono apparentemente in grado di caricare l'assemblaggio usando la riflessione:

[System.Reflection.Assembly]::LoadFrom($dllpath)

Anche se non capisco la differenza tra i metodi Load, LoadFrom o LoadFile, sembra che l'ultimo metodo funzioni.

Tuttavia, mi sembra ancora impossibile creare istanze o utilizzare oggetti. Ogni volta che provo, ricevo errori che descrivono che Powershell non è in grado di trovare nessuno dei tipi pubblici.

So che le lezioni ci sono:

$asm = [System.Reflection.Assembly]::LoadFrom($dllpath)
$cbbtypes = $asm.GetExportedTypes()
$cbbtypes | Get-Member -Static

---- inizio estratto ----

   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)

---- fine dell'estratto ----

Tentativo di utilizzare metodi statici non riesce, non so perché !!!

[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

Qualsiasi consiglio apprezzato !!

Risposte:


15

Potresti circondarlo Add-Typecon un tentativo try catch e stampare la proprietà LoaderExceptions, come dice l'errore da fare. Potrebbe fornire un'eccezione con un messaggio di errore più dettagliato.

try
{
    Add-Type -Path "C:\rnd\CloudBerry.Backup.API.dll"
}
catch
{
    $_.Exception.LoaderExceptions | %
    {
        Write-Error $_.Message
    }
}

9
Questo non ha funzionato per me, ma mi ha portato nel campo da baseball. All'interno della cattura, l'oggetto LoaderExceptions si trova qui: $ _. Exception.LoaderExceptions
Brett

non c'è un modo per usare il percorso relativo?
Entro il

3

Ho trovato questo link: http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html

Dice che ".LoadWithPartialName" è stato deprecato. Pertanto, invece di continuare a implementare Add-Type con quel metodo, utilizza una tabella statica interna per tradurre il "nome parziale" in un "nome completo". Nell'esempio fornito nella domanda, CloudBerry.Backup.API.dllnon è presente una voce nella tabella interna di PowerShell, motivo per cui [System.Reflection.Assembly]::LoadFrom($dllpath)funziona. Non sta usando la tabella per cercare un nome parziale.


2

Alcuni dei metodi sopra indicati non funzionavano per me o non erano chiari.

Ecco cosa uso per concludere le chiamate -AddPath e catturare 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)"
}

Riferimento
https://social.technet.microsoft.com/Forums/sharepoint/en-US/dff8487f-69af-4b64-ab83-13d58a55c523/addtype-inheritance-loaderexceptions


0

Ho usato la seguente configurazione per caricare un controllo csharp personalizzato in PowerShell. Consente di personalizzare e utilizzare il controllo all'interno di PowerShell.

ecco il link al blog

http://justcode.ca/wp/?p=435

ed ecco il link codeproject con source

http://www.codeproject.com/Articles/311705/Custom-CSharp-Control-for-Powershell


3
Benvenuti in Server Fault! Preferiamo davvero che le risposte contengano contenuto non puntatori al contenuto. Sebbene ciò possa teoricamente rispondere alla domanda, sarebbe preferibile includere qui le parti essenziali della risposta e fornire il collegamento come riferimento.
jscott

0

L' LoaderExceptionssono nascosti all'interno del record di errore. Se l'errore del tipo aggiuntivo era l'ultimo nell'elenco degli errori, utilizzare $Error[0].InnerException.LoaderExceptionsper mostrare gli errori. Molto probabilmente, la tua libreria dipende da un'altra che non è stata caricata. Puoi scegliere Add-Typeciascuno di essi o semplicemente creare un elenco e usare l' -ReferencedAssembliesargomento per Add-Type.


Prova $ Error [0] .Exception.LoaderExceptions e segui i consigli di Eris.
Tahir Hassan,

-1

Credo che ormai si POTREBBE hai trovato una risposta a questo fenomeno. Mi sono imbattuto in questo post dopo aver riscontrato lo stesso problema ... Ho potuto caricare l'assembly e visualizzare i tipi contenuti nell'assembly, ma non sono riuscito a istanziarne un'istanza da una classe statica. È stato EFTIDY. Ordinato, EFTidyNet.TidyNet.Options o cosa? Ooooo Weeee ... Problemi ... problemi ... potrebbe essere qualsiasi cosa. E guardando attraverso i metodi e i tipi statici della DLL non ha rivelato nulla di promettente. Ora mi stavo deprimendo. L'ho fatto funzionare in un programma C # compilato, ma per il mio uso ho voluto farlo funzionare in un linguaggio interpretato ... PowerShell.

La mia soluzione l'ho trovata ed è ancora in fase di dimostrazione, ma sono euforica e ho voluto condividerla. Costruisci una piccola app console.exe esercitando la funzione che mi interessava e quindi visualizzala in qualcosa che lo decompilasse o mostrasse il codice IL. Ho usato il riflettore di Red-Gate e il componente aggiuntivo del generatore di linguaggio PowerShell e Wallah! mostrava qual era la stringa del costruttore corretta! :-) Provalo. e spero che funzioni per chiunque si trovi di fronte a questo problema.


2
E ... qual era la stringa del costruttore corretta? Questo non risponde alla domanda nel modo in cui è scritto. Inoltre, benvenuto su ServerFault!
austinian il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.