如何正确地将.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程序集上使用相同的cmdlet,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

任何指导表示赞赏!

Answers:


15

您是否可以Add-Type用try catch 包围并打印LoaderExceptions属性,如错误所指出的那样。它可能会提供带有更详细的错误消息的异常。

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

9
这对我没有用,但使我陷入了困境。在捕获内,LoaderExceptions对象位于此处:$ _。Exception.LoaderExceptions
Brett

没有办法使用相对路径吗?
阿米特(Amit)2016年

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/zh-CN/dff8487f-69af-4b64-ab83-13d58a55c523/addtype-in​​heritance-loaderexceptions


0

我使用以下设置在Powershell中加载自定义csharp控件。它允许在Powershell中自定义和使用控件。

这是博客链接

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

这是与源代码的codeproject链接

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


3
欢迎来到服务器故障!我们确实确实希望答案包含内容而不是内容的指针。虽然从理论上讲这可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。
jscott

0

LoaderExceptions隐藏在错误记录中。如果add-type错误是错误列表中的最后一个错误,请使用$Error[0].InnerException.LoaderExceptions来显示错误。您的库很可能依赖于另一个尚未加载的库。您可以Add-Type每个人,也可以只列出一个清单,并使用的-ReferencedAssemblies参数Add-Type


尝试$ Error [0] .Exception.LoaderExceptions并遵循Eris的建议。
塔希尔·哈桑

-1

我想现在你MIGHT已经找到了答案,这现象。遇到相同的问题后,我跑了这篇文章...我可以加载程序集,并查看程序集中包含的类型,但是无法从静态类实例化它的一个实例。是EFTIDY。Tidy,EFTidyNet.TidyNet.Options或什么?Ooooo Weeee ...问题...问题...可能是任何事情。通过DLL的静态方法和类型查看并没有发现任何有希望的东西。现在我很沮丧。我让它在已编译的C#程序中工作,但是出于我的使用目的,我希望它以一种交错的语言... powershell运行。

我找到了我的解决方案,并且它仍在被证明,但是我很高兴并且想分享一下。构建一个小型的console.exe应用程序,执行我感兴趣的功能,然后以反编译或显示IL代码的方式查看它。我使用了Red-Gate的反射器,powershell语言生成器插件和Wallah!它显示了正确的构造函数字符串是什么!:-) 试试吧。我希望它对遇到此问题的任何人都有效。


2
而且...正确的构造函数字符串是什么?这并不能真正回答问题的编写方式。另外,欢迎使用ServerFault!
奥斯丁2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.