到目前为止,大多数人都知道System.Reflection.Assembly.LoadWithPartialName
已弃用该方法,但事实证明它的Add-Type -AssemblyName Microsoft.VisualBasic
行为并不比LoadWithPartialName
:
[Add-Type]不会尝试在系统的上下文中解析您的请求,而是查看静态的内部表,以将“部分名称”转换为“全名”。
如果您的“部分名称”未出现在其表中,则脚本将失败。
如果您的计算机上安装了多个版本的程序集,则没有智能算法可供选择。您将得到他们表中出现的任何一个,可能是较旧的,过时的。
如果您安装的版本比表中已过时的版本都新,则脚本将失败。
Add-Type没有像这样的“部分名称”的智能解析器
.LoadWithPartialNames
。
微软说你实际上应该做的是这样的:
Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
或者,如果您知道路径,则如下所示:
Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'
为程序集提供的长名称为Strong name,它是版本和程序集唯一的,有时也称为全名。
但这留下了几个问题无法回答:
如何确定具有给定部分名称的系统上实际加载的内容的强名称?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
这些也应该起作用:
Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
如果我希望脚本始终使用.dll的特定版本,但是不确定安装位置,那么如何确定.dll的强名呢?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
要么:
Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
如果知道强名,如何确定.dll路径?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
而且,以类似的方式,如果我知道所使用的程序的类型名称,那么我怎么知道它来自什么程序集?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
我如何查看可用的程序集?
我建议使用GAC PowerShell模块。 Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
效果很好。
- 如何查看
Add-Type
使用的列表?
这有点复杂。我可以描述如何使用.Net反射器访问任何版本的PowerShell(对于PowerShell Core 6.0,请参见下面的更新)。
首先,找出哪个库Add-Type
来自:
Get-Command -Name Add-Type | Select-Object -Property DLL
用反射器打开生成的DLL。我使用ILSpy是因为它是FLOSS,但是任何C#反射器都可以工作。打开该库,然后查找Microsoft.Powershell.Commands.Utility
。下Microsoft.Powershell.Commands
,应该有AddTypeCommand
。
在该代码清单中,有一个私有类InitializeStrongNameDictionary()
。这列出了将短名称映射为强名称的字典。我看过的库中有近750个条目。
更新:现在,PowerShell Core 6.0是开源的。对于该版本,您可以跳过上述步骤,直接在其GitHub存储库中在线查看代码。但是,我不能保证该代码与任何其他版本的PowerShell相匹配。