web-dev-qa-db-ja.com

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

インターネット上のすべての答えは私がアセンブリをロードする必要があることを書いている - 私は間違いなくエラーメッセージからそれを読むことができます:-) - 質問は:

どのようにアセンブリをロードしてスクリプトを機能させるのですか?

135
Baxter

LoadWithPartialNameは非推奨になりました。 PowerShell V3の推奨される解決策は、Add-Typeコマンドレットを使用することです。

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

複数の異なるバージョンがあり、あなたは特定のバージョンを選びたいと思うかもしれません。 :-)

165
Keith Hill
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
67
Shay Levy

ほとんどの人は今ではSystem.Reflection.Assembly.LoadWithPartialNameが廃止予定であることを知っていますが、Add-Type -AssemblyName Microsoft.VisualBasicLoadWithPartialNameよりも優れた動作はしません

システムのコンテキストで要求を解析しようとするのではなく、[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'

アセンブリに与えられたその長い名前は厳密な名前として知られています、そしてそれは両方バージョンとアセンブリにユニークです、そしてまた時々として知られていますフルネーム。

しかし、これは未解決のいくつかの質問を残します。

  1. 与えられた部分的な名前で私のシステムに実際にロードされているものの厳密な名前をどのように判断しますか

    [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
  1. スクリプトに常に特定のバージョンの.dllを使用させたいが、それがインストールされている場所がわからない場合は、どのようにして.dllから厳密な名前を判断しますか?

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

または

Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
  1. 厳密な名前がわかっている場合、.dllパスをどのように判断すればよいですか?

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

  2. そして、同様に、私が使っているものの型名を知っていれば、それがどのアセンブリから来ているのかをどうやって知ることができるでしょうか。

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

  3. どのようなアセンブリが利用可能かをどうやって確認できますか?

GAC PowerShellモジュール をお勧めします。 Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullNameはかなりうまくいきます。

  1. 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と一致することは保証できません。

36
Bacon Bits

アセンブリをロードしたい場合PowerShellセッション中はロックせずに、これを使用します。

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

$storageAssemblyPathはアセンブリのファイルパスです。

セッション内のリソースをクリーンアップする必要がある場合、これは特に便利です。たとえば、配置スクリプトなどです。

17
Martin Brandl

これが、PowerShell v1、v2、およびv3でアセンブリを読み込む方法の多数の例を含むブログ投稿です。

方法は次のとおりです。

  • ソースファイルから動的に
  • アセンブリから動的に
  • 他のコードタイプ、すなわちF#を使用する

v1.0 PowerShellセッションで.NETアセンブリを読み込む方法
v2.0 PowerShellスクリプト2.0でCSharp(C#)コードを使用
v3.0 Windows PowerShellで.NET Frameworkアセンブリを使用

15
Ralph Willgoss

あなたは全体の* .dllアセンブリをロードすることができます

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

答えのどれも私を助けなかった、従って私は私のために働いた解決策を投稿している、私がしなければならなかったすべてはSQLPSモジュールをインポートすることであった。どういうわけかアセンブリはそのモジュールで参照されました。

とにかく走れ:

Import-module SQLPS

注:SQLPSが廃止予定であることに注目してくれたJasonに感謝

代わりに実行してください。

Import-Module SqlServer

または

Install-Module SqlServer
4
Saul Cruz

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")は私のために働きました。

3
Tez Kurmala

LoadWithPartialNameを使うことができます。しかし、それは彼らが言ったように非推奨です。

あなたは確かにAdd-Typeと一緒に行くことができます、そしてあなたが.dllファイルのフルパスを指定したくないならば、あなたは単にすることができます:

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

私にはSQL Serverがインストールされていないためにエラーが返されました(私は推測しています)が、同じ考えでWindowsフォームアセンブリをロードすることができました。

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

MSDNサイトで特定のクラスに属する正確なアセンブリ名を見つけることができます。

Example of finding out Assembly name belonging to a particular class

2
ThomasMX

先頭にアセンブリ参照を追加してください。

必要なアセンブリSMOとSmoExtendedをロードします。

[System.Reflection.Assembly] :: LoadWithPartialName( "Microsoft.SqlServer.SMO")| Out-Null [System.Reflection.Assembly] :: LoadWithPartialName( "Microsoft.SqlServer.SmoExtended")。アウトヌル

0
Amrita Basu

以下の機能が順番にインストールされていることを確認してください

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"

0
shadi eftekhari