Как правильно добавить сборки .NET в сеанс Powershell?

24

У меня есть сборка .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

Любое руководство приветствуется!

amandion
источник

Ответы:

15

Не могли бы вы окружить Add-Typeобъект try catch и распечатать свойство LoaderExceptions, как об этом говорит ошибка. Это может предоставить исключение с более подробным сообщением об ошибке.

try
{
    Add-Type -Path "C:\rnd\CloudBerry.Backup.API.dll"
}
catch
{
    $_.Exception.LoaderExceptions | %
    {
        Write-Error $_.Message
    }
}
jessenich
источник
9
Это не сработало для меня, но заставило меня выйти на поле. Внутри улова объект LoaderExceptions находится здесь: $ _. Exception.LoaderExceptions
Бретт
нет ли способа использовать относительный путь?
Амит
3

Я нашел эту ссылку: 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)работает. Он не использует таблицу для поиска частичного имени.

Слогмейстер экстраординарный
источник
2

Некоторые из вышеперечисленных методов либо не сработали, либо были неясны.

Вот что я использую, чтобы обернуть вызовы -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)"
}

Ссылка
https://social.technet.microsoft.com/Forums/sharepoint/en-US/dff8487f-69af-4b64-ab83-13d58a55c523/addtype-inheritance-loaderexceptions

Ральф Виллгосс
источник
0

Я использовал следующую настройку, чтобы загрузить пользовательский элемент управления csharp в powershell. Это позволяет настраивать и использовать элемент управления из PowerShell.

вот ссылка на блог

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

и вот ссылка на кодпроект с источником

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

justcode_ca
источник
3
Добро пожаловать в сбой сервера! Мы действительно предпочитаем, чтобы ответы содержали контент, а не указатели на контент. Хотя это может теоретически ответить на вопрос, было бы предпочтительным включить здесь основные части ответа и предоставить ссылку для справки.
Jscott
0

Они LoaderExceptionsскрыты внутри записи об ошибке. Если ошибка типа добавления была последней в списке ошибок, используйте $Error[0].InnerException.LoaderExceptionsдля отображения ошибок. Скорее всего, ваша библиотека зависит от другой, которая не была загружена. Вы можете либо Add-Typeкаждый, либо просто составить список и использовать -ReferencedAssembliesаргумент для Add-Type.

Эрис
источник
Попробуйте $ Error [0] .Exception.LoaderExceptions и следуйте советам Эрис.
Тахир Хасан
-1

Я думаю, что теперь вы МОГЛИ нашли ответ на эти явления. Я столкнулся с этим сообщением после того, как столкнулся с той же проблемой ... Я мог загрузить сборку и просмотреть типы, содержащиеся в сборке, но не смог создать экземпляр этого экземпляра из статического класса. Это было EFTIDY. Tidy, EFTidyNet.TidyNet.Options или что? О-о-о-о-о-о-о-о-о-о ... проблемы ... проблемы ... это может быть что угодно. И просмотр статических методов и типов DLL не выявил ничего многообещающего. Теперь я впал в депрессию. Он работал в скомпилированной программе на C #, но для моего использования я хотел, чтобы он работал на языке с интерпретами ... powershell.

Мое решение я нашел, и оно все еще проверяется, но я в восторге и хочу поделиться этим. Создайте небольшое приложение console.exe, используя интересующую меня функцию, а затем просмотрите его во что-нибудь, что могло бы декомпилировать его или показать код IL. Я использовал отражатель Red-Gate, надстройку генератора языка PowerShell и Wallah! это показало, какая правильная строка конструктора была! :-) Попытайся. и я надеюсь, что это работает для тех, кто сталкивается с этой проблемой.

Ким Д. Александр
источник
2
И ... какая была правильная строка конструктора? Это на самом деле не отвечает на вопрос так, как он написан. Кроме того, добро пожаловать в ServerFault!
австрийский