J'ai un assemblage .NET (une dll) qui est une API pour sauvegarder le logiciel que nous utilisons ici. Il contient certaines propriétés et méthodes dont j'aimerais tirer parti dans mes scripts Powershell. Cependant, je rencontre de nombreux problèmes avec le premier chargement de l'assembly, puis l'utilisation de l'un des types une fois l'assembly chargé.
Le chemin d'accès complet au fichier est:
C:\rnd\CloudBerry.Backup.API.dll
Dans Powershell, j'utilise:
$dllpath = "C:\rnd\CloudBerry.Backup.API.dll"
Add-Type -Path $dllpath
J'obtiens l'erreur ci-dessous:
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.
Utiliser la même applet de commande sur un autre assemblage .NET, DotNetZip , qui contient des exemples d'utilisation des mêmes fonctionnalités sur le site ne fonctionne pas non plus pour moi.
Je trouve finalement que je suis apparemment capable de charger l'Assemblée en utilisant la réflexion:
[System.Reflection.Assembly]::LoadFrom($dllpath)
Bien que je ne comprenne pas la différence entre les méthodes Load, LoadFrom ou LoadFile, cette dernière méthode semble fonctionner.
Cependant, il me semble toujours impossible de créer des instances ou d'utiliser des objets. Chaque fois que j'essaye, j'obtiens des erreurs qui décrivent que Powershell est incapable de trouver l'un des types publics.
Je sais que les cours sont là:
$asm = [System.Reflection.Assembly]::LoadFrom($dllpath)
$cbbtypes = $asm.GetExportedTypes()
$cbbtypes | Get-Member -Static
---- début de l'extrait ----
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 de l'extrait ----
Essayer d'utiliser des méthodes statiques échoue, je ne sais pas pourquoi !!!
[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
Toute orientation appréciée !!
Pourriez-vous entourer le Add-Type
avec un try catch et imprimez la propriété LoaderExceptions, comme l'erreur indique de le faire. Il peut fournir une exception avec un message d'erreur plus détaillé.
try
{
Add-Type -Path "C:\rnd\CloudBerry.Backup.API.dll"
}
catch
{
$_.Exception.LoaderExceptions | %
{
Write-Error $_.Message
}
}
J'ai trouvé ce lien: http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html
Il dit que ".LoadWithPartialName" est obsolète. Par conséquent, au lieu de continuer à implémenter Add-Type avec cette méthode, il utilise une table interne statique pour traduire le "nom partiel" en "nom complet". Dans l'exemple donné dans la question, CloudBerry.Backup.API.dll
N'a pas d'entrée dans la table interne de PowerShell, c'est pourquoi [System.Reflection.Assembly]::LoadFrom($dllpath)
fonctionne. Il n'utilise pas la table pour rechercher un nom partiel.
Certaines des méthodes ci-dessus n'ont pas fonctionné pour moi ou n'étaient pas claires.
Voici ce que j'utilise pour encapsuler les appels -AddPath et intercepter les 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)"
}
Les LoaderExceptions
sont cachés dans l'enregistrement d'erreur. Si l'erreur de type d'ajout était la dernière de la liste d'erreurs, utilisez $Error[0].InnerException.LoaderExceptions
pour afficher les erreurs. Très probablement, votre bibliothèque dépend d'une autre qui n'a pas été chargée. Vous pouvez soit Add-Type
chacun, ou faites simplement une liste et utilisez le -ReferencedAssemblies
argument à Add-Type
.
J'ai utilisé la configuration suivante pour charger un contrôle csharp personnalisé dans PowerShell. Il permet au contrôle d'être personnalisé et utilisé à partir de PowerShell.
voici le lien du blog
et voici le lien codeproject avec la source
http://www.codeproject.com/Articles/311705/Custom-CSharp-Control-for-Powershell