Wie füge ich der Powershell-Sitzung richtig .NET-Assemblys hinzu?

24

Ich habe eine .NET-Assembly (eine DLL), die eine API für die hier verwendete Sicherungssoftware ist. Es enthält einige Eigenschaften und Methoden, die ich in meinen Powershell-Skripten verwenden möchte. Es treten jedoch viele Probleme auf, wenn ich erst die Assembly lade und dann einen der Typen verwende, sobald die Assembly geladen ist.

Der vollständige Dateipfad lautet:

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

In Powershell verwende ich:

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

Ich erhalte den folgenden Fehler:

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.

Die Verwendung desselben Cmdlets in einer anderen .NET-Assembly, DotNetZip , mit Beispielen für die Verwendung derselben Funktionalität auf der Site, funktioniert bei mir ebenfalls nicht.

Irgendwann stelle ich fest, dass ich die Assembly scheinbar mithilfe von Reflektion laden kann:

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

Obwohl ich den Unterschied zwischen den Methoden Load, LoadFrom oder LoadFile nicht verstehe, scheint diese letzte Methode zu funktionieren.

Es scheint mir jedoch immer noch nicht möglich zu sein, Instanzen zu erstellen oder Objekte zu verwenden. Bei jedem Versuch erhalte ich Fehler, die beschreiben, dass Powershell keinen der öffentlichen Typen finden kann.

Ich weiß, dass der Unterricht dort ist:

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

---- Auszugsbeginn ----

   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)

---- Ende des Ausschnitts ----

Der Versuch, statische Methoden zu verwenden, schlägt fehl, ich weiß nicht warum !!!

[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

Jede Anleitung wird gebeten !!

amandion
quelle

Antworten:

15

Könnten Sie das Add-Typemit einem try catch umgeben und die LoaderExceptions-Eigenschaft drucken, da der Fehler angibt, dies zu tun. Möglicherweise wird eine Ausnahme mit einer ausführlicheren Fehlermeldung angezeigt.

try
{
    Add-Type -Path "C:\rnd\CloudBerry.Backup.API.dll"
}
catch
{
    $_.Exception.LoaderExceptions | %
    {
        Write-Error $_.Message
    }
}
jessenich
quelle
9
Das hat bei mir nicht funktioniert, aber es hat mich in den Ballpark gebracht. Innerhalb des Catch befindet sich das LoaderExceptions-Objekt hier: $ _. Exception.LoaderExceptions
Brett
Gibt es keine Möglichkeit, den relativen Pfad zu verwenden?
Amit
3

Ich fand diesen Link: http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html

Er sagt, dass ".LoadWithPartialName" veraltet ist. Anstatt Add-Type weiterhin mit dieser Methode zu implementieren, wird daher eine statische interne Tabelle verwendet, um den "Teilnamen" in einen "vollständigen Namen" zu übersetzen. In dem in der Frage angegebenen Beispiel CloudBerry.Backup.API.dllist kein Eintrag in der internen Tabelle von PowerShell vorhanden, weshalb dies [System.Reflection.Assembly]::LoadFrom($dllpath)funktioniert. Die Tabelle wird nicht zum Nachschlagen eines Teilnamens verwendet.

Slogmeister Extraordinaire
quelle
2

Einige der oben genannten Methoden haben bei mir entweder nicht funktioniert oder waren unklar.

Folgendes verwende ich, um -AddPath-Aufrufe umzubrechen und LoaderExceptions abzufangen:

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)"
}

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

Ralph Willgoss
quelle
0

Ich habe das folgende Setup verwendet, um ein benutzerdefiniertes csharp-Steuerelement in Powershell zu laden. Es ermöglicht die individuelle Anpassung und Nutzung der Steuerung innerhalb von Powershell.

Hier ist der Blog-Link

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

Und hier ist der Code-Projekt-Link mit der Quelle

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

justcode_ca
quelle
3
Willkommen bei Server Fault! Wir bevorzugen wirklich, dass Antworten Inhalte enthalten, die nicht auf Inhalte verweisen. Während dies theoretisch die Frage beantworten mag, wäre es vorzuziehen , die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen.
Jscott
0

Sie LoaderExceptionssind im Fehlerdatensatz versteckt. Wenn der Add-Type-Fehler der letzte in der Fehlerliste war, verwenden Sie $Error[0].InnerException.LoaderExceptions, um die Fehler anzuzeigen. Höchstwahrscheinlich ist Ihre Bibliothek von einer anderen Bibliothek abhängig, die nicht geladen wurde. Sie können entweder Add-Typejeden einzeln oder einfach eine Liste erstellen und das -ReferencedAssembliesArgument dazu verwenden Add-Type.

Eris
quelle
Probieren Sie $ Error [0] .Exception.LoaderExceptions und befolgen Sie die Empfehlungen von Eris.
Tahir Hassan
-1

Inzwischen haben Sie wahrscheinlich eine Antwort auf dieses Phänomen gefunden. Ich bin auf diesen Beitrag gestoßen, nachdem ich auf dasselbe Problem gestoßen war ... Ich konnte die Assembly laden und die in der Assembly enthaltenen Typen anzeigen, konnte jedoch keine Instanz davon aus einer statischen Klasse instanziieren. War es EFTIDY? Ordentlich, EFTidyNet.TidyNet.Options oder was? Ooooo weeee ... Probleme ... Probleme ... es könnte alles sein. Ein Blick auf die statischen Methoden und Typen der DLL ergab keine vielversprechenden Ergebnisse. Jetzt wurde ich depressiv. Ich hatte es in einem kompilierten C # -Programm arbeiten, aber für meine Verwendung wollte ich, dass es in einer interpeted Sprache läuft ... Powershell.

Meine Lösung habe ich gefunden und sie wird noch bewiesen, aber ich bin hocherfreut und wollte sie teilen. Erstellen Sie eine kleine console.exe-App, die die von mir gewünschte Funktion ausführt, und zeigen Sie sie dann in einer Form an, die sie dekompiliert oder den IL-Code anzeigt. Ich habe den Reflektor von Red-Gate und das Add-In für den Powershell-Sprachgenerator und Wallah! Es zeigte, was der richtige Konstruktor-String war! :-) Versuch es. und ich hoffe, es funktioniert für alle, die mit diesem Problem konfrontiert sind.

Kim D. Alexander
quelle
2
Und ... was war der richtige Konstruktor-String? Dies beantwortet die Frage nicht wirklich so, wie sie geschrieben ist. Willkommen auch bei ServerFault!
Austin