如何在PowerShell中加载程序集?

以下PowerShell代码

#Get a server object which corresponds to the default instance $srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server ... rest of the script ... 

给出以下错误信息:

 New-Object : Cannot find type [Microsoft.SqlServer.Management.SMO.Server]: make sure the assembly containing this type is loaded. At C:\Users\sortelyn\ ... \tools\sql_express_backup\backup.ps1:6 char:8 + $srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand 

在互联网上的每一个答案写道,我必须加载程序集 – 以及确保我可以从错误信息中读取:-) – 问题是:

你如何加载程序集并使脚本工作?

LoadWithPartialName已被弃用。 推荐的PowerShell V3解决scheme是使用Add-Type cmdlet,例如:

 Add-Type -Path 'C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.Smo.dll' 

有多个不同的版本,你可能想select一个特定的版本。 🙂

 [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") 

现在大多数人都知道System.Reflection.Assembly.LoadWithPartialName已被弃用,但事实certificateAdd-Type -AssemblyName Microsoft.VisualBasic 行为不如LoadWithPartialName

[Add-Type]查看静态内部表,将“部分名称”转换为“全名”,而不是尝试在系统上下文中parsing请求。

如果您的“部分名称”没有出现在他们的表中,您的脚本将失败。

如果您的计算机上安装了多个版本的程序集,则没有智能algorithm可供select。 你会得到任何一个出现在他们的表,可能是旧的,过时的。

如果您安装的版本比表中的旧版本更新,则脚本将失败。

Add-Type没有像“ .LoadWithPartialNames ”这样的“部分名称”智能parsing器。

微软说你实际上应该做的是这样的:

 Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 

或者,如果你知道path,就像这样:

 Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll' 

这个长长的名字被称为强名 ,这个名字对于版本和程序集来说都是独一无二的,有时也被称为全名。

但是这留下了一些未解答的问题:

  1. 我如何确定使用给定的部分名称在系统上实际加载的强名称?

    [System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location; [System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;

  2. 如果我希望我的脚本始终使用.dll的特定版本,但是我无法确定它的安装位置,我如何确定.dll的强名称?

    [System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;

  3. 如果我知道强名,我该如何确定.dllpath?

    [Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;

  4. 而且,以类似的方式,如果我知道我使用的是什么types的名称,我怎么知道它是从哪里来的?

    [Reflection.Assembly]::GetAssembly([Type]).Location

  5. 我如何查看可用的组件?

我build议使用GAC PowerShell模块 。 Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName工作得很好。

  1. 我怎样才能看到Add-Type使用的列表?

这有点复杂。 我没有在网上看到任何logging的清单,但我可以描述如何使用.Netreflection器访问它。

首先,找出哪个库的Add-Type来自:

 Get-Command -Name Add-Type | Select-Object -Property DLL 

用你的reflection器打开产生的DLL。 我为此使用了ILSpy ,因为是FLOSS,但是任何C#reflection器都可以工作。 打开该库,然后查看Microsoft.Powershell.Commands.Utility 。 在Microsoft.Powershell.Commands ,应该有AddTypeCommand 。 在代码清单中,有一个私有类, InitializeStrongNameDictionary() 。 列出了将短名称映射到强名称的字典。 我看过的图书馆里有近750个参赛作品。

以下是一些博客文章,介绍了在PowerShell v1,v2和v3中加载程序集的方法示例。

方法包括:

  • dynamic地从一个源文件
  • dynamic从一个程序集
  • 使用其他代码types,即F#

v1.0 如何在PowerShell会话中加载.NET程序集
v2.0 在PowerShell脚本2.0中使用CSharp(C#)代码
v3.0 在Windows PowerShell中使用.NET Framework程序集

如果要在PowerShell会话期间加载程序集而不locking它 ,请使用以下命令:

 $bytes = [System.IO.File]::ReadAllBytes($storageAssemblyPath) [System.Reflection.Assembly]::Load($bytes) 

其中$storageAssemblyPath是您的程序集的文件path。

如果您需要清理会话中的资源,这尤其有用。 例如在部署脚本中。

您可以加载整个* .dll程序集

 $Assembly = [System.Reflection.Assembly]::LoadFrom("C:\folder\file.dll"); 

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")为我工作。

你可以使用LoadWithPartialName 。 但是,正如他们所说,这已经被废弃了。

您确实可以使用Add-Type ,除了其他答案之外,如果您不想指定.dll文件的完整path,则只需执行以下操作:

 Add-Type -AssemblyName "Microsoft.SqlServer.Management.SMO" 

对我来说,这返回了一个错误,因为我没有安装SQL Server(我猜),但是,与此相同的想法,我能够加载Windows窗体大会:

 Add-Type -AssemblyName "System.Windows.Forms" 

您可以在MSDN站点上find属于特定类的精确程序集名称:

查找属于特定类的程序集名称的示例

没有答案帮助我,所以我发布的解决scheme,为我工作,我所要做的就是导入SQLPS模块,我意识到这一点,当我意外地运行了Restore-SqlDatabase命令,并开始工作,这意味着该组件以某种方式在该模块中被引用。

赶紧跑:

 Import-module SQLPS 

在顶部添加程序集引用。

加载所需的组件SMO和SmoExtended。

[System.Reflection.Assembly] :: LoadWithPartialName(“Microsoft.SqlServer.SMO”)| Out-Null [System.Reflection.Assembly] :: LoadWithPartialName(“Microsoft.SqlServer.SmoExtended”)| 外空

确保您具有以下function按顺序安装

1 – 用于SQL Server的Microsoft系统CLRtypes

2-Microsoft SQL Server共享pipe理对象

3个Microsoft Windows PowerShell扩展

你也可能需要加载

Add-Type -Path“C:\ Program Files \ Microsoft SQL Server \ 110 \ SDK \ Assemblies \ Microsoft.SqlServer.Smo.dll”

Add-Type -Path“C:\ Program Files \ Microsoft SQL Server \ 110 \ SDK \ Assemblies \ Microsoft.SqlServer.SqlWmiManagement.dll”