次の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の推奨される解決策は、Add-Type
コマンドレットを使用することです。
Add-Type -Path 'C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.Smo.dll'
複数の異なるバージョンがあり、あなたは特定のバージョンを選びたいと思うかもしれません。 :-)
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
ほとんどの人は今では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'
アセンブリに与えられたその長い名前は厳密な名前として知られています、そしてそれは両方バージョンとアセンブリにユニークです、そしてまた時々として知られていますフルネーム。
しかし、これは未解決のいくつかの質問を残します。
与えられた部分的な名前で私のシステムに実際にロードされているものの厳密な名前をどのように判断しますか
[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をリフレクタで開きます。これはFLOSSなので ILSpy を使っていますが、どのC#リフレクタでも動作するはずです。そのライブラリを開き、Microsoft.Powershell.Commands.Utility
を調べます。 Microsoft.Powershell.Commands
の下にはAddTypeCommand
があるはずです。
そのためのコードリストには、プライベートクラスInitializeStrongNameDictionary()
があります。これは、短い名前を厳密な名前にマップする辞書をリストします。私が見た図書館には約750のエントリがあります。
更新:PowerShell Core 6.0がオープンソースになりました。そのバージョンでは、上記のステップを飛ばして直接コードを見ることができます 彼らのGitHubレポジトリにオンラインで 。ただし、そのコードが他のバージョンのPowerShellと一致することは保証できません。
アセンブリをロードしたい場合PowerShellセッション中はロックせずに、これを使用します。
$bytes = [System.IO.File]::ReadAllBytes($storageAssemblyPath)
[System.Reflection.Assembly]::Load($bytes)
$storageAssemblyPath
はアセンブリのファイルパスです。
セッション内のリソースをクリーンアップする必要がある場合、これは特に便利です。たとえば、配置スクリプトなどです。
これが、PowerShell v1、v2、およびv3でアセンブリを読み込む方法の多数の例を含むブログ投稿です。
方法は次のとおりです。
v1.0 PowerShellセッションで.NETアセンブリを読み込む方法
v2.0 PowerShellスクリプト2.0でCSharp(C#)コードを使用
v3.0 Windows PowerShellで.NET Frameworkアセンブリを使用
あなたは全体の* .dllアセンブリをロードすることができます
$Assembly = [System.Reflection.Assembly]::LoadFrom("C:\folder\file.dll");
答えのどれも私を助けなかった、従って私は私のために働いた解決策を投稿している、私がしなければならなかったすべてはSQLPSモジュールをインポートすることであった。どういうわけかアセンブリはそのモジュールで参照されました。
とにかく走れ:
Import-module SQLPS
注:SQLPSが廃止予定であることに注目してくれたJasonに感謝
代わりに実行してください。
Import-Module SqlServer
または
Install-Module SqlServer
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
は私のために働きました。
LoadWithPartialName
を使うことができます。しかし、それは彼らが言ったように非推奨です。
あなたは確かにAdd-Type
と一緒に行くことができます、そしてあなたが.dllファイルのフルパスを指定したくないならば、あなたは単にすることができます:
Add-Type -AssemblyName "Microsoft.SqlServer.Management.SMO"
私にはSQL Serverがインストールされていないためにエラーが返されました(私は推測しています)が、同じ考えでWindowsフォームアセンブリをロードすることができました。
Add-Type -AssemblyName "System.Windows.Forms"
MSDNサイトで特定のクラスに属する正確なアセンブリ名を見つけることができます。
先頭にアセンブリ参照を追加してください。
[System.Reflection.Assembly] :: LoadWithPartialName( "Microsoft.SqlServer.SMO")| Out-Null [System.Reflection.Assembly] :: LoadWithPartialName( "Microsoft.SqlServer.SmoExtended")。アウトヌル
以下の機能が順番にインストールされていることを確認してください
SQL Server用の1 - MicrosoftシステムのCLRタイプ
2 - Microsoft SQL Server共有管理オブジェクト
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"