У меня есть сборка .NET (dll), которая представляет собой API для резервного копирования программного обеспечения, которое мы здесь используем. Он содержит некоторые свойства и методы, которые я хотел бы использовать в своих сценариях Powershell. Однако я сталкиваюсь с множеством проблем при первой загрузке сборки, а затем использовании любого из типов после загрузки сборки.
Полный путь к файлу:
C:\rnd\CloudBerry.Backup.API.dll
В Powershell я использую:
$dllpath = "C:\rnd\CloudBerry.Backup.API.dll"
Add-Type -Path $dllpath
Я получаю сообщение об ошибке ниже:
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.
Используя тот же командлет в другой сборке .NET, DotNetZip, в котором есть примеры использования того же функционала на сайте, у меня тоже не работает.
В конце концов я обнаружил, что, похоже, могу загрузить сборку с помощью отражения:
[System.Reflection.Assembly]::LoadFrom($dllpath)
Хотя я не понимаю разницы между методами Load, LoadFrom или LoadFile, этот последний метод, похоже, работает.
Однако мне все еще кажется, что я не могу создавать экземпляры или использовать объекты. Каждый раз, когда я пытаюсь это сделать, я получаю ошибки, которые описывают, что Powershell не может найти ни один из общедоступных типов.
Я знаю, что там есть классы:
$asm = [System.Reflection.Assembly]::LoadFrom($dllpath)
$cbbtypes = $asm.GetExportedTypes()
$cbbtypes | Get-Member -Static
---- начало отрывка ----
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)
---- конец отрывка ----
Попытка использовать статические методы терпит неудачу, не знаю почему !!!
[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
Любое руководство приветствуется !!
Не могли бы вы окружить Add-Type
с помощью try catch и распечатайте свойство LoaderExceptions в соответствии с сообщением об ошибке. Он может предоставить исключение с более подробным сообщением об ошибке.
try
{
Add-Type -Path "C:\rnd\CloudBerry.Backup.API.dll"
}
catch
{
$_.Exception.LoaderExceptions | %
{
Write-Error $_.Message
}
}
Я нашел эту ссылку: http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html
Он говорит, что ".LoadWithPartialName" устарел. Поэтому вместо того, чтобы продолжать реализацию Add-Type с этим методом, он использует статическую внутреннюю таблицу для преобразования «частичного имени» в «полное имя». В примере, приведенном в вопросе, CloudBerry.Backup.API.dll
не имеет записи во внутренней таблице PowerShell, поэтому [System.Reflection.Assembly]::LoadFrom($dllpath)
работает. Таблица не используется для поиска частичного имени.
Некоторые из вышеперечисленных методов либо не работали для меня, либо были непонятны.
Вот что я использую для обертывания вызовов -AddPath и перехвата исключений 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)"
}
В LoaderExceptions
скрыты внутри записи об ошибке. Если ошибка типа добавления была последней в списке ошибок, используйте $Error[0].InnerException.LoaderExceptions
чтобы показать ошибки. Скорее всего, ваша библиотека зависит от другой, которая не была загружена. Вы также можете Add-Type
каждый, или просто составьте список и используйте -ReferencedAssemblies
аргумент Add-Type
.
Я использовал следующую настройку для загрузки настраиваемого элемента управления csharp в PowerShell. Это позволяет настраивать и использовать элемент управления из PowerShell.
вот ссылка на блог
а вот ссылка на код проекта с источником
http://www.codeproject.com/Articles/311705/Custom-CSharp-Control-for-Powershell
Я думаю, к настоящему времени ты МОЩЬ нашли ответ на это явление. Я наткнулся на этот пост после того, как столкнулся с той же проблемой ... Я мог загрузить сборку и просмотреть типы, содержащиеся в сборке, но не смог создать ее экземпляр из статического класса. Было ли это EFTIDY. Приборка, EFTidyNet.TidyNet.Options что ли? Ooooo Weeee ... Проблемы ... проблемы ... это может быть что угодно. И просмотр статических методов и типов DLL ничего многообещающего не выявил. Теперь я впадал в депрессию. У меня он работал в скомпилированной программе C #, но для моего использования я хотел, чтобы он работал на языке с интерполяцией ... PowerShell.
Я нашел свое решение, и оно все еще проверяется, но я в восторге и хотел им поделиться. Создайте небольшое приложение console.exe, выполняющее интересующую меня функцию, а затем просмотрите его в том, что могло бы декомпилировать его или показать код IL. Я использовал рефлектор Red-Gate и надстройку генератора языка PowerShell и Wallah! он показал, что такое правильная строка конструктора! :-) Попытайся. и я надеюсь, что это сработает для тех, кто сталкивается с этой проблемой.