以下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
互联网上的每个答案都写道我必须加载程序集 - 确保我可以从错误信息中读取:-) - 问题是:
如何加载程序集并使脚本有效?
答案 0 :(得分:165)
LoadWithPartialName
已被弃用。 PowerShell V3的推荐解决方案是使用Add-Type
cmdlet,例如:
Add-Type -Path 'C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.Smo.dll'
有多个不同版本,您可能想要选择特定版本。 : - )
答案 1 :(得分:67)
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
答案 2 :(得分:35)
大多数人现在都知道System.Reflection.Assembly.LoadWithPartialName
已被弃用,但事实证明Add-Type -AssemblyName Microsoft.VisualBasic
does not behave much better than 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'
为程序集指定的长名称称为强名称,它对于版本和程序集都是唯一的,有时也称为全名。
但这留下了几个未回答的问题:
如何使用给定的部分名称确定系统上实际加载内容的强名称?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
如果我希望我的脚本始终使用.dll的特定版本,但我无法确定它的安装位置,如何确定.dll的强名称是什么?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
如果我知道强名称,我如何确定.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 module。 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是开源的。对于该版本,您可以跳过上述步骤直接查看代码online in their GitHub repository。但是,我无法保证该代码与任何其他版本的PowerShell匹配。
答案 3 :(得分:17)
如果要在PowerShell会话期间加载程序集而不锁定它,请使用:
$bytes = [System.IO.File]::ReadAllBytes($storageAssemblyPath)
[System.Reflection.Assembly]::Load($bytes)
其中$storageAssemblyPath
是程序集的文件路径。
如果您需要清理会话中的资源,这将非常有用。例如,在部署脚本中。
答案 4 :(得分:15)
以下是一些博客文章,其中包含许多在PowerShell v1,v2和v3中加载程序集的方法示例。
方法包括:
v1.0 How To Load .NET Assemblies In A PowerShell Session
v2.0 Using CSharp (C#) code in PowerShell scripts 2.0
v3.0 Using .NET Framework Assemblies in Windows PowerShell
答案 5 :(得分:7)
您可以使用
加载整个* .dll程序集$Assembly = [System.Reflection.Assembly]::LoadFrom("C:\folder\file.dll");
答案 6 :(得分:4)
没有一个答案对我有帮助,所以我发布了适用于我的解决方案,我所要做的就是导入SQLPS模块,我意外地实现了这一点,我运行了Restore-SqlDatabase命令并开始工作,意味着该模块以某种方式引用了该程序集。
跑步:
Import-module SQLPS
注意:感谢Jason注意到SQLPS已被弃用
改为运行:
Import-Module SqlServer
或
Install-Module SqlServer
答案 7 :(得分:3)
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
为我工作。
答案 8 :(得分:2)
您可以使用LoadWithPartialName
。但是,正如他们所说,这已被弃用。
您确实可以使用Add-Type
,除了其他答案之外,如果您不想指定.dll文件的完整路径,您只需执行以下操作:
Add-Type -AssemblyName "Microsoft.SqlServer.Management.SMO"
对我来说这返回了一个错误,因为我没有安装SQL Server(我猜),但是,有了同样的想法,我能够加载Windows窗体程序集:
Add-Type -AssemblyName "System.Windows.Forms"
您可以在MSDN网站上找到属于特定类的精确程序集名称:
答案 9 :(得分:0)
在顶部添加装配参考。
[System.Reflection.Assembly] :: LoadWithPartialName(" Microsoft.SqlServer.SMO")|外空 [System.Reflection.Assembly] :: LoadWithPartialName(" Microsoft.SqlServer.SmoExtended")|出空
答案 10 :(得分:0)
确保按顺序安装以下功能
SQL Server的1-Microsoft System CLR类型
2-Microsoft SQL Server共享管理对象
3-Microsoft Windows PowerShell Extensions
您也可能需要加载
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”