WMI の FAQ: トラブルシューティングとヒントメモ: このドキュメントは、当初「Windows Management Instrumentation : よく寄せられる質問」として発行されたものです。
トピック
Q 1. WMI はどのようなツールで、どのような機能を提供しますか。Windows Management Instrumentation (WMI) は、Windows 管理技術の中核を担っています。WMI は、ローカル コンピュータとリモート コンピュータの両方の管理に使用できます。WMI は、プログラミング言語やスクリプト言語で日常的な管理タスクを実行するための一貫したアプローチを提供します。たとえば、次のようなことが可能です。
ローカル コンピュータまたはリモート コンピュータ上の Windows イベント ログを照会できます。 WMI (Windows Management Instrumentation) の Instrumentation という単語は "計器" や "計器による測定" を意味します。ちょうど自動車の計器類がエンジンに関する情報を示すように、WMI はコンピュータ システムの内部状態に関する情報を示します。WMI では、Windows システム内に検出されたディスクやプロセスなどのオブジェクトをモデリングすることにより、"計器情報" を提供します。WMI によるシステム オブジェクトのモデリングには、Win32_LogicalDisk や Win32_Process などのクラスが使用されます。クラス名から推察できるように、Win32_LogicalDisk はコンピュータ上の論理ディスクをモデリングするクラス、Win32_Process はコンピュータ上で現在稼動している任意のプロセスをモデリングするクラスです。クラスは、Common Information Model (CIM) と呼ばれる拡張可能スキーマに基づいています。CIM スキーマは、Distributed Management Task Force (http://www.dmtf.org) の公開規格です。 WMI には、上記のほか、イベント処理、リモート処理、クエリ処理、ビュー、スキーマのユーザー拡張、情報取得などの機能もあります。 Q 2. WMI はどのプラットフォームに対応していますか。WMI は、最近のバージョンの Windows すべてに対応しています。Windows Me、Windows 2000、Windows XP、および Windows Server 2003 では WMI が標準でインストールされます。 Windows 98 および Windows NT 4.0 の場合は、http://www.microsoft.com/japan/downloads から WMI をダウンロードしてインストールすることができます。ダウンロード名 "Windows Management Instrumentation (WMI) SDK 1.5 (Windows 95/98/NT 4.0)" を検索してください。 なお、Windows NT 4.0 に WMI をインストールして実行するには、事前に Service Pack 4 以降を適用しておく必要があります。 WMI を使用するには、さらに以下のソフトウェアが必要です。
Q 3. WMI で特定の機能が公開されているかどうかを調べるにはどうすればよいですか。WMI とその機能に関する詳細なリファレンス情報をお探しなら、MSDN を参照することをぜひお勧めします。http://msdn.microsoft.com/en-us/library/aa394572.aspx に用意されている『WMI Reference』(英語) をご覧ください。『WMI Reference』には、WMI の標準インストールに含まれているクラス、スクリプト オブジェクト、および API がほぼすべて網羅されています。なお、オペレーティング システムに付属していない WMI プロバイダによって作成されるクラスは、MSDN に情報が記載されていないことがありますが、Platform SDK に情報が記載されている場合もあります。 情報がどのようにカテゴリ分けされているかを理解しておくと、クラスを検索したり、必要な機能が用意されているかどうかを調べたりするときに役立ちます。特定のタスクを実行するために複数のクラスが必要になることもあります。たとえば、コンピュータの基本的なシステム情報を取得する場合を考えてみましょう。Win32_OperatingSystem クラスを使うと、使用可能メモリに関する情報を取得できますが、コンピュータ上の空きディスク容量に関する情報も併せて取得するには、別のクラス (Win32_LogicalDisk など) を使用する必要があります。WMI で何ができ、何ができないかについては、「あるバージョンの Windows で実行できるスクリプトを他のバージョンの Windows で実行できないのですが、これはなぜですか」の質問を参照してください。 Windows 2000 以降のプラットフォームでは、CIM Studio というツールを使って WMI クラスを参照できます。このツールに関する情報とこのツールのダウンロード ファイルについては、http://www.microsoft.com/japan にアクセスし、キーワード "WMI ツール" で検索してください。なお、CIM Studio は WMITools.exe によってインストールされるファイルの 1 つです。また、サポート外ですが、WMI と共に自動的にインストールされる Wbemtest.exe ユーティリティで WMI データを参照することも可能です。 Windows XP と Windows Server 2003 では、下記のスクリプトを使うと、クラス名に特定の文字列が含まれているクラスを検索できます。このスクリプトを使用するには、Search.vbs という名前のテキスト ファイルとして保存します。実行時に検索対象のキーワードを指定します。たとえば、クラス名に "service" が含まれているクラスを検索するには、コマンド プロンプトから次のコマンドを実行します。 |
cscript search.vbs service
' Script for finding a class in WMI Repository
Set args = wscript.arguments
If args.Count <= 0 Then
Wscript.Echo "Tool to search for a matching class in the WMI Repository. "
Wscript.Echo "USAGE: <keywordToSearch> [<namespaceToSearchIn>]"
Wscript.Echo "Example1: Cscript search.vbs service"
Wscript.Echo "Example2: Cscript search.vbs video root\cimv2"
Else
' If no Namespace is specified then the Default is the ROOT namespace
rootNamespace = "\\.\ROOT"
keyword = args(0)
If args.Count > 1 Then
rootNamespace = args(1)
End If
EnumNameSpace rootNamespace
Wscript.Echo vbNewLine
End if
' Subroutine to recurse through the namespaces
Sub EnumNameSpace(parentNamespaceName)
Set objService = GetObject("winmgmts:" & parentNamespaceName)
Set collMatchingClasses = objService.Execquery _
("Select * From meta_class Where __class " & _
"Like '%" & keyword & "%'")
If (collMatchingClasses.count > 0) Then
Wscript.Echo vbNewLine
Wscript.Echo vbNewLine
Wscript.Echo "Matching Classes Under Namespace: " & parentNamespaceName
For Each matchingClass in collMatchingClasses
Wscript.Echo " " & matchingClass.Path_.CLASS
Next
End if
Set collSubNamespaces = objService.Execquery _
("select * from __namespace")
For Each subNameSpace in collSubNamespaces
EnumNameSpace subNameSpace.path_.namespace + _
"\" + subNameSpace.Name
Next
End Subこのスクリプトは、Windows XP および Server 2003 でのみ動作します。これは、WMI クエリ言語に含まれている LIKE 演算子は、この 2 つのプラットフォームでしか使用できないためです。
実際にスクリプトを作成しているうち、目的のタスクを WMI では実行できなかったり、WMI では効率性に欠けるというようなケースに遭遇することが考えられます。このような場合は、最初にオペレーティング システムに用意されている他のスクリプト技術で目的の機能が提供されていないかどうかをチェックしてください。たとえば、ADSI (Active Directory サービス インターフェイス) を使えば Active Directory を管理でき、CDO (Collaboration データ オブジェクト) を使えばスクリプト内から電子メールを送信できます。Windows オペレーティング システムに適切なスクリプト インターフェイスがない場合は、目的の機能を実行できるサード パーティ ソフトウェアの使用を検討してください。
スクリプト インターフェイスがない場合は、目的の機能を提供する WMI プロバイダを作成することができます。ただし、WMI プロバイダはスクリプト言語では作成できず、C++ または C# で作成する必要があります。詳細については、従来型 WMI プロバイダの作成に関する指示が記載されている MSDN の「Using WMI」を参照してください。.NET Framework を使ってプロバイダを作成したい場合は、MSDN ライブラリから "WMI によるアプリケーションの管理" を検索してください。
WMI の機能を拡張するソフトウェアが多数のサード パーティから市場に出されています。サード パーティ ツールは、インターネットから検索できます。また、ニュースグループへの質問を通じて情報を得ることも考えられます。「WMI を使用しているサンプル スクリプトはどこにありますか」の質問を参照してください。
MSDN (Microsoft Developers Network) および TechNet は共にサンプルの宝庫です。この 2 つのサイト上の役立つページへのリンクを、次にいくつか示します。
| • | TechNet スクリプト センター 技術および管理タスク別に分類された数百種類のサンプルがあります。 http://www.microsoft.com/japan/technet/scriptcenter/default.mspx. |
| • | MSDN http://msdn.microsoft.com/library/default.aspx WMI スクリプトについては、"WMI System Administration scripts" を検索してください。 WMIC (WMI コマンド ライン ユーティリティ) については、http://msdn.microsoft.com/en-us/library/aa394531.aspx (英語) を参照してください。 |
| • | WMI Software Developers Kit (SDK) カテゴリ別の問題解決方法については、「Using WMI」から「WMI Tasks for Scripts and Applications」を参照してください。http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en |
| • | Windows 2000 Scripting Guide オンライン (英語) 完全版のオンライン ガイドです。WMI サンプル スクリプトが豊富に用意されています。 http://www.microsoft.com/technet/scriptcenter/guide/default.mspx |
| • | TechNet 上の「Tales from the Script」コラム 初級および中級向けのスクリプト トピック。 http://www.microsoft.com/japan/technet/community/columns/scripts/default.mspx |
| • | MSDN の「SCRIPTING CLINIC」コラム 上級者用スクリプト トピック http://www.microsoft.com/japan/msdn/columns/default.aspx |
主な原因として、新しいバージョンの Windows に用意されているクラス、プロパティ、およびメソッドが以前のバージョンの Windows では使用できないことが考えられます。使用できるかどうかを確認するには、MSDN ライブラリ (http://msdn.microsoft.com/library/default.aspx) WMI Software Developer Kit (SDK) の各クラスに関する「Requirements」の項をチェックしてください。たとえば、Win32_PingStatus クラスの必要条件には、オペレーティング システムが Windows XP または Windows Server 2003 であることが含まれています。このため、スクリプトから Windows 2000 上の Win32_PingStatus クラスにアクセスしようとすると、スクリプトの実行に失敗し "クラスが見つかりません" のエラーが返されます。
同様に、SNMP プロバイダなどの WMI データ プロバイダには、特定のオペレーティング システムにしか対応していないものや、WMI の既定インストールに含まれていないものがあります。SDK では、トピック内でこれらのプロバイダに言及するとき、「About WMI」のトピック「Operating System Availability」へのリンクがメモ欄に示されています。
標準 WMI プロバイダの一覧については、「WMI Reference」の「WMI Providers」を参照してください。
一般に、新しいバージョンの Windows に新しいプロバイダが追加されても、そのプロバイダの機能が以前のバージョンの Windows で使用できるようになることはありません。たとえば、Ping プロバイダで定義されている Win32_PingStatus クラスを Windows 2000 でも使用できるようになる見込みはありません。プロバイダが新しいバージョンの Windows の機能を利用する場合、その機能が以前のバージョンに用意されていなければ、このような結果になります。
この他に、同じバージョンの Windows を 2 台のコンピュータで使用していても、一方では実行できるスクリプトをもう一方では実行できない場合もありますが、これは何らかの問題が生じていることを意味します。このような問題のトラブルシューティングについては、「WMI スクリプトの実行時にエラーが返されるのですが、何が原因でしょうか」を参照してください。
最初に、そのエラーが本当に WMI エラーかどうかを確かめてください。WMI のエラー番号は 8004xxxx で始まります (例 : 80041001)。WMI エラー番号と戻りコードについては、http://msdn.microsoft.com/library/default.aspx にアクセスし、「WMI Return Codes」を参照してください。必要な情報が見つからない場合は、MSDN でエラー番号を検索してみてください。
スクリプトの実行時にエラー番号が表示されなかった場合は、%windir%\system32\wbem\logs フォルダ内の WMI ログ ファイルを開くと、エラー番号を見つけることができます。実行したスクリプトが原因で発生したエラーがどれかを判断しにくい場合は、ログ全体を削除し、スクリプトを再度実行します。こうすると、スクリプトに関連するエラーを特定しやすくなります。
ログ ファイルを調べてもエラーが見つからない場合は、ログ ファイルのログ レベルを必要に応じて再設定します。情報の詳細度を最も高くするには、ログ レベルを詳細モードに設定します。Windows 2000、Windows NT、および Windows Me/98/95 ではログ レベル変更後に WMI を再起動する必要がありますが、Windows XP および Windows Server 2003 ではその必要はありません。ログ レベルの構成の詳細については、http://msdn.microsoft.com/library/default.aspx にアクセスし、「Logging WMI Activity」を検索してください。
Windows イベント ログにエラーが記録されることもあります。ソースが Winmgmt になっているイベントを探してください。
Windows XP または Windows Server 2003 では MSFT_WMIProvider クラスを使うと、プロバイダのロードとアンロード、クエリへの応答、メソッドの実行などのプロバイダ操作をトラブルシューティングできます。たとえば、プロバイダがクエリへの応答をキャンセルする直前に MSFT_WmiProvider_CancelQuery_Pre クラスのインスタンスが WMI から生成されます。さらに、キャンセル後には MSFT_WmiProvider_CancelQuery_Post クラスのインスタンスが生成されます。特定のスクリプトのクエリ操作が失敗する場合は、これらのイベント クラスが生成されるまで待機する監視用スクリプトを作成することで対処できます。これらのイベント クラスを監視用スクリプトが受信したときに、関係しているプロバイダとその種類、処理中のクエリ、および関連している名前空間を判別することができます。
詳細については、http://msdn.microsoft.com/library/default.aspx にアクセスし、「Troubleshooting Classes」を検索してください。
下記のサンプル スクリプトでは、Ping プロバイダに関する問題をトラブルシューティングします。このスクリプトは、Ping 実行中に発生したすべてのイベント (プロバイダのロード、クエリの受信、エラーの発生など) を報告します。この情報に基づいて、プロバイダに問題があるのか、WMI サービスに問題があるのかを判断することができます。出力された情報のうち、ResultCode が 0 以外のイベントを探してください。一般に、0 以外のエラー コードは操作の失敗を示します。
下記のコードを .VBS ファイルに保存して、スクリプトを実行します。
Option Explicit
Sub Sink_OnObjectReady(oInst, oCtx)
instcount = instCount+1
Wscript.echo "Event " & cstr(instCount) & vbTab & _
oInst.GetObjectText_ & vbNewLine
End Sub
Sub Sink_OnCompleted(Hresult, oErr, oCtx)
End Sub
'msftTroubleShooting.vbs starts here
DIM oLctr, oSvc, OSink, instCount, SrvName, SrvUserName, SrvPswd, args, argcount
Set args = wscript.arguments
SrvName = "."
SrvUserName = Null
SrvPswd = Null
instcount = 0
argcount = args.Count
If (argcount > 0) Then
If args(0) = "/?" or args(0) = "?" Then
Wscript.Echo "Usage: cscript msftTroubleShooting.vbs " _
[ServerName=Null|?] [UserName=Null] [Password=Null]"
Wscript.Echo "Example: cscript msftTroubleShooting.vbs "
Wscript.Echo "Example: cscript msftTroubleShooting.vbs computerABC"
Wscript.Echo "Example: cscript msftTroubleShooting.vbs "
Wscript.Echo "computerABC admin adminPswd"
Wscript.Quit 1
End If
End If
Set oLctr = createObject("WbemScripting.Swbemlocator")
On Error Resume Next
If argcount = 0 Then
Set oSvc = oLctr.ConnectServer(,"root\cimv2")
SrvName = " Local Computer "
Else
srvname = args(0)
If argcount >= 2 Then
SrvUserName = args(1)
End If
If argcount >= 3 Then
SrvPswd = args(2)
End If
Set oSvc = oLctr.ConnectServer(srvname,"root\cimv2",SrvUserName,SrvPswd)
End If
If Err = 0 Tthen
Wscript.Echo "Connection to " & srvname & " is thru" & vbNewLine
Else
Wscript.Echo "The Error is " & err.description & _
" and the Error number is " & err.number
Wscript.Quit 1
End If
On Error Goto 0
Set oSink = WScript.CreateObject("WbemScripting.SWbemSink","Sink_")
oSvc.ExecNotificationQueryAsync oSink, _
"Select * From MSFT_WmiProvider_OperationEvent Where " & _
"provider = 'WMIPingProvider'"
Wscript.Echo "To stop the script press ctrl + C" & vbNewLine
Wscript.Echo "Waiting for events......" & vbNewLine
While True
Wscript.Sleep 10000
Wendスクリプトの実行時、CIM Studio などの WMI ベースのツールの実行時、または WMI コントロールの使用時には、WMI サービスに関する問題が発生することがあります。スクリプトが実行されなかったり、"アクセスは拒否されました" というエラー メッセージが表示されたりすることがあります。このエラーの原因としては、WMI が動作していないか、名前空間が正しく構成されていないかのどちらかが考えられます。また、クラスを提供している WMI プロバイダがロードされていない場合や、WMI リポジトリ (クラス定義の格納場所) が壊れた場合にも、エラーが発生することがあります。
WMI サービスに関する問題をトラブルシューティングするには、次の作業を行います。
リモート コンピュータへの接続に関して問題が生じている場合は、他の操作を行う前にローカル コンピュータ上でスクリプトを実行してみてください。ローカル コンピュータ上でスクリプトを実行できるのであれば、「WMI でリモート コンピュータを管理するにはどうすればよいですか」のトピックを参照してください。ローカル コンピュータでスクリプトを実行できない場合は、次のトラブルシューティング手順を実行してください。
ローカル コンピュータ上での WMI 操作が失敗し、予期せぬエラー コードが返される場合や、WMI コントロールを起動できない場合は、ローカル WMI サービスが稼動しているかどうかを確認します。下記のコードを .VBS ファイルに保存して、コマンド プロンプトからスクリプトを実行します。
Set Svc = GetObject ("winmgmts:root\default")スクリプトを実行できるのであれば、WMI サービスは稼動しており、WMI サービス自体に問題はないと考えることができます。
スクリプトが失敗した場合は、スクリプト内で指定されている名前空間が正しい名前空間かどうかを確認します。サンプル スクリプトでは、root\default 名前空間への接続を試行します。この名前空間が存在しない場合は、多くの場合、WBEM_E_INVALID_NAMESPACE (0x8004100E) エラーが返されます。
名前空間が存在していても、接続先のクラスが存在していないとスクリプトの実行が失敗します。その場合は、そのクラスにアクセスしようとした時点で次のいずれかのエラー コードが返される可能性があります。
クラスへの接続失敗は、WMI リポジトリが壊れていることが原因の場合もあります。その場合は、次のいずれかのエラー コードが返される可能性があります。
リポジトリが壊れていると思われる場合は、リポジトリを再構築するのが最善策となります。
WMI サービス (winmgmt) は常時稼動しているのが普通です。このサービスはコンピュータの起動時に稼動を開始し、コンピュータがシャットダウンされない限り停止されません。このサービスが何らかの原因で停止してしまった場合は、コマンド プロンプトから「net start winmgmt」と入力すると再起動することができます。さらに、WMI ベースのツール (Wbemtest など) やスクリプトで WMI 名前空間に接続したときには、WMI サービスが必ず自動的に再起動されるようになっています。WMI サービスが停止しているときに WMI を使用するスクリプトを実行すると、通常は、WMI サービスが自動的に再起動されます。
WMI サービスに関する問題が発生している場合は、サービスを手動で停止および再起動しなければならなくなることがあります。手順は次のとおりです。
WMI リポジトリは %systemDrive%\%windir%\system32\wbem\Repository フォルダにあり、WMI プロバイダによって作成されたクラス定義の一元的な保存場所となります。リポジトリの破損が疑われる場合は、リポジトリを再構築することができます。ただし、リポジトリを再構築すると、WMI (またはオペレーティング システム) をインストールした後で追加された WMI 情報がリポジトリから失われる可能性があります。その場合は、リポジトリ内の元の位置に情報が格納されるように、対応するアプリケーションを手動で実行して情報を復元する必要が生じます。リポジトリを再構築するには、次の操作を行います。
WMI リポジトリを手動で再構築するには、次の手順を実行します。
C:\WINDOWS\system32\WBEM\cimwin32.mof
C:\WINDOWS\system32\WBEM\cimwin32.mfl
C:\WINDOWS\system32\WBEM\system.mof
C:\WINDOWS\system32\WBEM\wmipcima.mof
C:\WINDOWS\system32\WBEM\wmipcima.mfl
Mofcomp C:\WINDOWS\system32\WBEM\cimwin32.mof
Mofcomp C:\WINDOWS\system32\WBEM\cimwin32.mfl
Mofcomp C:\WINDOWS\system32\WBEM\system.mof
Mofcomp C:\WINDOWS\system32\WBEM\wmipcima.mof
Mofcomp C:\WINDOWS\system32\WBEM\wmipcima.mfl
root\default に接続できない場合は、WMI コンポーネントが正しく登録されていない可能性があります。WMI で使用する .DLL ファイルと .EXE ファイルは %windir%\system32\wbem に置かれます。このディレクトリに格納されているすべての .DLL ファイルと .EXE ファイルの再登録が必要になることがあります。また、64 ビット システムを使用している場合は、%windir%\sysWOW64\wbem 内の .DLL ファイルと .EXE ファイルについても再登録が必要になることがあります。
この段階でまだ root\default に接続できない場合は、オペレーティング システムを再インストールする必要があります。Windows を再インストールしてから、スクリプトをもう一度実行してみてください。
マイクロソフト製品サポートサービスに問い合わせる
WMI がどうしても動作しない場合は、マイクロソフト製品サポート サービス (PSS) に問い合わせる必要があります。詳細については、http://support.microsoft.com/default.aspx を参照してください。
名前空間セキュリティは、WMI コントロールを通じて管理できます。WMI コントロールを起動するには、コマンド プロンプトに次のコマンドを入力します。
wmimgmt
Windows 9x コンピュータまたは Windows NT4 コンピュータに WMI をインストールしている場合は、上記の代わりに次のコマンドを入力します。
wbemcntl.exe
また、次の方法で WMI コントロールの [セキュリティ] タブにアクセスすることもできます。
メモ
一般に、WMI でローカル コンピュータに対して実行できる操作は、ローカル管理者特権でアクセスできるリモート コンピュータに対しても実行可能です。リモート名前空間へのアクセス権を持っているユーザー (「WMI 名前空間セキュリティを設定するにはどうすればよいですか」参照) は、リモート管理が有効になっているリモート コンピュータに接続して、自分にアクセス許可が与えられている任意の操作を実行することができます。さらに、リモート コンピュータで委任が有効になっていれば、委任を行うこともできます。委任を行うと、リモート コンピュータでクライアントによって提供された資格情報を使用して、さらに別のコンピュータから情報を取得することが可能です。つまり、コンピュータ A でスクリプトを実行してコンピュータ B に接続することができ、コンピュータ B ではコンピュータ A 上のスクリプトから渡されたユーザー名とパスワードを使用してコンピュータ C に接続することができます。委任のシナリオについては、「リモート操作に 3 台目のコンピュータが関与している場合にリモート操作が失敗するのですが、何が原因でしょうか」のトピックを参照してください。
Set objWMIService = GetObject("winmgmts:\\TargetComputer”)
Set objWMIService = GetObject("winmgmts:\\DomainName\TargetComputer”)
必須ではありませんが、モニカ自体の中に WMI 名前空間を指定することもできます。複数の異なるプラットフォームを扱っている場合は、オペレーティング システムによって既定名前空間が異なる可能性があるので、WMI 名前空間を指定しておくことをお勧めします。たとえば、Windows 2000、Windows XP、および Windows Server 2003 では root\cimv2 が既定の名前空間となりますが、Windows NT 4.0 および Windows 98 では root\defaul が既定の名前空間となります。
次のモニカでは、リモート コンピュータ TargetComputer 上の root\cimv2 名前空間に接続します。
Set objWMIService = GetObject("winmgmts:\\TargetComputer\root\cimv2)
Set objWMIService = GetObject _
("winmgmts:{impersonationLevel=Impersonate}!\\TargetComputer\root\cimv2")
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate," _ &
"authenticationLevel=pkt}!\\ _
TargetComputer\root\cimv2")
wbemImpersonationLevelImpersonate = 3
wbemAuthenticationLevelPktPrivacy = 6
Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer _
("TargetComputer", "root\cimv2", "UserName", "Password")
objService.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate
objservices.Security_.AuthenticationLevel = wbemAuthenticationLevelPktPrivacy
メモ 一般に、管理者パスワードをスクリプト内にハードコーディングすることはお勧めできません。実行のたびに、スクリプトからパスワードを要求するプロンプトを表示するようにしてください。
詳細については、http://msdn.microsoft.com/library/default.aspx にアクセスし、「Connecting Between Different Operating Systems」を検索してください。
リモート名前空間へのアクセス権があり、接続先のコンピュータでリモート処理が有効化されていれば、接続時にユーザー名とパスワードを指定する必要はありません。この場合は、WMIC が現在のユーザー資格情報を使用して自動的に接続を行います。次に、例を示します。
WMIC /NODE:"computer1" OS GET Caption,CSDVersion,CSName
委任を行う必要がある場合は、WMIC 接続文字列に /IMPLEVEL:Delegate と /AUTHORITY の設定を含めます。次に、例を示します。
WMIC /NODE:"computer1" /IMPLEVEL:Delegate /AUTHORITY:"Kerberos:domain\computer1" OS
上記の代わりに、WMIC 経由で接続するときに使用するユーザー アカウントとパスワードを明示的に指定することもできます。なお、WMI スクリプトの場合と同様、既定で WMI リモート接続特権が付与されるのは管理者だけです。次に、例を示します。
WMIC /NODE:"computer1" /USER:"domainname\username" OS GET Caption,CSDVersion
次のサンプル コマンドでは、ユーザー名と共にパスワードを指定しています。
WMIC /NODE:"computer1" /USER:"domainname\username" /PASSWORD:"userpassword" OS GET Caption,CSDVersion,CSName
リモート接続の詳細については、http://msdn.microsoft.com/library/default.aspx にアクセスし、「Connecting to WMI on a Remote Computer」を検索してください。
リモート WMI 名前空間またはリモート WMI オブジェクトに接続しようとしたときに "アクセスは拒否されました" エラーが表示されることがあります。"アクセスは拒否されました" エラーには、種類がいくつかあります。
0x80041003 (WBEM_E_ACCESS_DENIED)
このエラーは、主に、必要な WMI 特権が付与されていないプロセスが名前空間にアクセスしようとした場合に発生します。リモート アクセスを開始するアカウントは、ターゲット コンピュータ上の管理者になっている必要があります。さらに、アカウントに対して特定の特権が有効になっていることが必要になる場合もあります。
このエラーをトラブルシューティングするには、リモート名前空間上の名前空間セキュリティをチェックして、アカウントに対して有効になっている特権を確認します。
0x80070005 (DCOM ACCESS_DENIED)
このエラーは、リモート サーバーが接続ユーザーを認識しないか、または接続ユーザーに何らかの制限がかかっている (ユーザーがロックアウトされているなど) 場合に発生します。このエラーが最も発生しがちなのは、アカウントが異なるドメインに所属している場合です。また、次のように、WMI セキュリティに対して最近加えられた変更との関連でこのエラーが発生することもあります。
0x800706xx (DCOM RPC error)
このエラーは、リモート コンピュータ上でファイアウォールが構成されている場合に発生しがちです。DCOM によるリモート管理が可能になるように、ファイアウォール上の適切なポートを開放する必要があります。
また、IP とホスト名のマッピングに関する問題がコンピュータに生じていることもあります。そのような問題の可能性をチェックするには、次のように接続文字列内でホスト名の代わりに IP アドレスを使用してみてください。
Set objWMIService = GetObject("winmgmts:\\192.168.1.1")リモートエラーをトラブルシューティングするには
クライアント コンピュータ (コンピュータ A) からリモート サーバー (コンピュータ B) を介して 3 台目のコンピュータ (コンピュータ C) にドメイン資格情報を転送する場合は、委任が必要になります。このように、特定の操作に対して複数のネットワーク ホップを行う必要があるときには委任が必要です。委任を行わないと、コンピュータ B がコンピュータ A から受信した資格情報を転送できず、その結果、コンピュータ C への接続が失敗します。
委任が必要になるシナリオを次に 2 つ示します。
上記のシナリオで委任を行うには、次の条件を満たす必要があります。
上記の手順を完了すると、コンピュータ B が委任対象として信頼されます。たとえば、コンピュータ B がコンピュータ C 上のリモート ファイル共有に要求を送信したとします。この場合、コンピュータ C 側では、転送された資格情報に基づいて、コンピュータ A 上のクライアント プロセスで指定されているユーザーを認証します。
委任は管理オプションの 1 つとして用意されていますが、コンピュータ A からコンピュータ B に資格情報が渡されることから、一般には委任の使用はお勧めできません。委任を受けたコンピュータ B では、他の用途に資格情報を使用することも可能になるため、セキュリティ上のリスクが生じます。
下記のスクリプトでは、Active Directory 内でコンピュータ アカウントに対して委任を有効にします。このスクリプトのテストは、ドメイン管理者アカウントを使用して Windows Server 2003 ドメイン内で行いました。このほか、テスト時の条件は次のとおりです。
'Purpose: Script to enable delegation on a computer and
'then perform an operation that requires delegation
'Requirements: The client computer must be a member of the same Active Directory
'domain as the WMI Server specified in the argument to this script
'Permissions required: The user that runs this script should be a member of
'the Domain Administrators group in the Active Directory
Const UF_TRUSTED_FOR_DELEGATION = &H80000
Set args = Wscript.Arguments
' Terminate unless two arguments are specified when starting
'the script
If args.Count <> 2 then
Wscript.Echo "You must provide a server name and delegation command line."
Wscript.Echo "For example, start the script using syntax similar to this:"
Wscript.Echo "cscript.exe this.vbs <WMI Server> <Delegation Command Line>"
Wscript.Echo "cscript.exe this.vbs computer2 "
Wscript.echo "\\computer1\c$\windows\system32\calc.exe"
Wscript.Quit 1
end if
serverName = args(0)
argCommandLine = args(1)
' Connect locally and get the domain and DS_Computer object to
' examine and/or modify
Set svc = GetObject("winmgmts:root\cimv2")
' Get some local machine variables to understand the environment we are working in
Set objEnum = svc.ExecQuery _
("Select domain, name From win32_computerSystem", "WQL", 48)
For Each obj in objEnum
domain = obj.Domain
computerName = obj.Name
Next
' Get the connection to the root\directory\ldap namespace to enable delegation
' on the remote computer from the local machine
Set svc = GetObject("Winmgmts:root\directory\ldap")
' Create the required context object
Set octx = CreateObject("wbemscripting.swbemnamedvalueset")
octx.Add "__PUT_EXT_PROPERTIES", Array("ds_userAccountControl")
octx.Add "__PUT_EXTENSIONS", true
octx.Add "__PUT_EXT_CLIENT_REQUEST", true
' Variable to determine whether or not we have modified the userAccountControl
'and whether or not we have to modify it back when we are done
modified = False
Set objEnum = svc.ExecQuery _
("Select * From ds_computer Where ds_cn = '" & serverName & "'", "WQL", 48)
For Each obj in objEnum
' Store this variable to memory for restoration after this operation completes
userAccountControlOriginal = obj.ds_userAccountControl
' Test to see if the computer is already trusted for delegation
If CBool(userAccountControlOriginal And UF_TRUSTED_FOR_DELEGATION ) = False Then
Wscript.Echo "Computer account not trusted for delegation yet"
' Resume On Error while we try this initially
On Error Resume Next
' Add this constant value to the value contained already
obj.ds_userAccountControl = userAccountControlOriginal + _
UF_TRUSTED_FOR_DELEGATION
' This should trust the computer account for delegation
obj.Put_ 1, octx
If (Err.Number = 0) Then
' Set the flag so we know to modify it back to original setting
modified = True
Else
Wscript.Echo Hex(Err.Number) & " " & _
Err.Description
Wscript.Quit 1
End If
On Error Goto 0:
Else
' Already trusted for delegation so
' continue with delegation code here
Wscript.Echo "Computer account is trusted for delegation already"
End If
' Get the locator object
Set lctr = CreateObject("WbemScripting.SWbemLocator")
' Get the service object from the remote server specifying the Kerberos authority
Set delegationService = lctr.ConnectServer _
(serverName, "root\cimv2", , , , _
"kerberos:" & trim(domain) & "\" & Trim(serverName))
' Delegation level impersonation
delegationService.Security_.ImpersonationLevel = 4
' Get the object that will be used to test the delegation hop
Set process = delegationService.Get("win32_process")
' Get the inparameter object for the method
Set inparams = process.methods_("Create").inparameters
' Set the inparameter commandline value
inparams.CommandLine = argCommandLine
' Execute the method
Set oReturn = process.ExecMethod_("Create", inparams)
' Echo the output
If (oReturn.ReturnValue = 0) Then
Wscript.Echo oReturn.ProcessId & _
" is the Process ID from the process " & _
"creation using delegation"
Else
Wscript.Echo "An error occurred, the return value for the " & _
"Win32_Process.Create method is " & _
oReturn.ReturnValue
End If
' Set the value back to the original value
If modified = True Then
' Subtract the added delegation privilege from the computer account
obj.ds_userAccountControl = _
userAccountControlOriginal - UF_TRUSTED_FOR_DELEGATION
' Restore the original setting
obj.put_ 1, octx
End If
Next上記のスクリプトは、2 つのメンバ コンピュータのどちらかで Windows NT 4.0 または Windows 98 が稼動している場合には動作しません。また、ターゲットが Windows NT 4.0 ファイル共有上に存在する場合にも、このスクリプトを実行できません。
手動でコンピュータを委任対象として信頼するには、次の操作を行います。
委任およびリモート接続の詳細については、「Connecting to a 3rd Computer-Delegation」(http://msdn.microsoft.com/en-us/library/aa389288.aspx) (英語) および「Securing a Remote WMI Connection」(http://msdn.microsoft.com/en-us/library/aa393266.aspx) (英語) を参照してください。
また、「WMI でリモート コンピュータを管理するにはどうすればよいですか」および「WMI 名前空間セキュリティを設定するにはどうすればよいですか」の質問も参照してください。
一般に、クエリが返すデータの量が多いと、クエリが完了するまでにかかる時間が長くなります。データのサブセットだけを取得できればよいのにクエリから要求するデータセットの規模が大きい場合は、返される情報を制限することで処理を高速化できることがよくあります。WQL (WMI Query Language) では、返されるプロパティ (フィールド) にもインスタンス (レコード) のセットにもフィルタをかけることができます。その例については、http://msdn.microsoft.com/library/default.aspx (英語) にアクセスし、「Querying with WQL」を検索してください。また、「SELECT Statement for Data Queries」のトピックも参照してください。
プロバイダによっては、特定のプロパティに基づいてフィルタをかけることを前提として最適化が行われていることがあります。その場合は、WHERE 句の中で適切なフィルタ条件を指定すると、データ空間全体が列挙された後で WMI がコレクションにフィルタをかけるのではなく、プロバイダがアクティブに結果セットにフィルタをかけることができるようになり、パフォーマンスが向上することがあります。このように最適化されたプロパティの例としては、CIM_DataFile の Drive プロパティと Path プロパティがあります。
既定では、コレクションを複数回、両方向に走査することが可能な列挙体が WMI クエリから返されます。これにより、コレクション内のすべての項目をループした後、必要に応じてすべての項目を繰り返しループすることなどが可能です。返されるデータ セットが大きい場合は、この種類の列挙体によるメモリ消費が大きくなるため、パフォーマンスが低下することがあります。この問題は、クエリの実行時に WBEM_FLAG_FORWARD_ONLY フラグを設定することで回避できます。この種類の列挙体を使用してコレクションを 1 回だけループすることも可能ですが、各オブジェクトに使用しているメモリは使用後に解放されるので、パフォーマンスは低下しません。詳細については、「Semisynchronous Call with VBScript」(http://msdn.microsoft.com/en-us/library/aa392301.aspx) (英語) を参照してください。
ほとんどの場合、半同期クエリのパフォーマンスは非同期クエリと同等ですが、クエリの規模が大きい場合は、アプリケーションのメイン スレッドがクエリによって占有されたり、システムの過負荷を避けるために WMI がクエリを抑制したりすることがあります。このような場合は、クエリを非同期にするとパフォーマンスを向上できます。ただし、ほとんどのオペレーティング システムでは、非同期呼び出しはセキュリティが低くなるので注意が必要です。詳細については、「Asynchronous Query」(http://msdn.microsoft.com/en-us/library/aa391396.aspx) (英語) および「Setting Security on an Asynchronous Call」(http://msdn.microsoft.com/en-us/library/aa393614.aspx) (英語) を参照してください。
WMI には、Windows インストーラによってインストールされたアプリケーションを表す Win32_Product クラスがあります。ただし、[プログラムの追加と削除] に表示されるアプリケーションでも、この WMI クラスによるリストに含まれないものがあります。この問題を解決する方法の 1 つとして、レジストリからインストール済みアプリケーションのデータを収集することができます。ただし、インストール時にレジストリへの書き込みを行わないアプリケーションもあります。このトピックでは、スクリプトを使ってレジストリから情報を直接読み出す方法と、MOF ファイルとスクリプトを使って WMI から情報を取得する方法の 2 つを示します。
strHost = "."
Const HKLM = &H80000002
Set objReg = GetObject("winmgmts://" & strHost & _
"/root/default:StdRegProv")
Const strBaseKey = _
"Software\Microsoft\Windows\CurrentVersion\Uninstall\"
objReg.EnumKey HKLM, strBaseKey, arrSubKeys
For Each strSubKey In arrSubKeys
intRet = objReg.GetStringValue(HKLM, strBaseKey & strSubKey, _
"DisplayName", strValue)
If intRet <> 0 Then
intRet = objReg.GetStringValue(HKLM, strBaseKey & strSubKey, _
"QuietDisplayName", strValue)
End If
If (strValue <> "") and (intRet = 0) Then
WScript.Echo strValue
End If
Next
qualifier dynamic:ToInstance;
qualifier ProviderClsid:ToInstance;
qualifier ClassContext:ToInstance;
qualifier propertycontext:ToInstance;
[dynamic, provider("RegProv"),
ProviderClsid("{fe9af5c0-d3b6-11ce-a5b6-00aa00680c3f}"),
ClassContext
("local|HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
]
class Products {
[key] string KeyName;
[read, propertycontext("DisplayName")] string DisplayName;
[read, propertycontext("DisplayVersion")] string DisplayVersion;
[read, propertycontext("InstallLocation")] string InstallLocation;
};
strComputer = "."
Set WMI = GetObject("winmgmts:\\" & strComputer & _
"\root\default")
Set colItems = WMI.ExecQuery("Select * from Products")
For Each objItem In colItems
WScript.Echo "DisplayName: " & objItem.DisplayName
WScript.Echo "DisplayVersion: " & objItem.DisplayVersion
WScript.Echo "InstallLocation: " & objItem.InstallLocation
WScript.Echo "KeyName: " & objItem.KeyName
Next
Windows XP では、WMI を通じてパフォーマンス データをすばやく簡単に取得できる "Cooked Counter プロバイダ" が初めてサポートされるようになりました。Windows 2000 でもパフォーマンス データを取得することが可能ですが、"加工" されていないデータが表示されるので、ほとんどのカウンタの場合、有用な値が得られるようにデータの書式を整える必要が生じます。これに対し、Windows XP および Windows Server 2003 のパフォーマンス データは、Win32_PerfFormattedData クラスから直接取得できます。
Windows 2000 では Cooked Counter プロバイダを使用できないので、有意なパフォーマンス情報を得るには "未加工" のデータに対して計算を行う必要があります。
各種カウンタの正しい計算式を見つけるには、最初に WMI SDK (「Performance Counter Classes」のトピック) を参照するか、または目的のプロパティの "countertype" プロパティを調べて、目的のプロパティの数値カウンタ タイプを特定する必要があります。そのカウンタ タイプの計算式を「WMI Performance Counter Types」(http://msdn.microsoft.com/en-us/library/aa394569.aspx) (英語) から探してください。
Windows 2000 より前のシステムで WMI を使ってパフォーマンス カウンタを取得するには、パフォーマンス モニタ プロバイダを使用する必要があります。「Monitoring Performance With the Performance Monitoring Provider」(http://msdn.microsoft.com/en-us/library/aa392398.aspx) (英語) を参照してください。