[WMI基礎] トラブルシュートの基礎知識 (1)/n : WMI の動作基盤のテストから始めよう v1.1

皆さんごきげんよう。ういこです。

ついに 4 月!新入社員の皆さま就職おめでとうございます。今月は多分「基礎から知ってみようシリーズ」をお届する見込みは予定です。今日は、その第一弾「WMI トラブルシュートの基礎知識」をお送りしたいと思います。

************************************************
★ 関連トピック ★
[WMI基礎] トラブルシュートの基礎知識 (2)/n : WMI 詳細ログと WMIDiag ダイジェスト
https://blogs.technet.com/jpilmblg/archive/2010/04/05/wmi-2-n-wmi-wmidiag.aspx
(2010/04/05 Up)
************************************************

はじめに : WMI ってそもそも何さ?
Windows Management Instrumentation (WMI) は OS に付属する管理基盤です。管理基盤ってことは何かを管理するわけですが、たとえばプロセスやアプリケーション、サービスの情報からハードウエア情報など、コンピュータ上の機能のかなりの部分を管理する仕組みみたいなものです。
まあ要は簡単にシステムの管理をするために用意された機能と思っていればだいたい合ってます。

今は微妙に知らない人もいるかもしれない Windows Millennium (Windows Me : サポート提供終了) 以降、Windows 2000 から現行 OS の Windows 7 まで搭載されています。
Windows 95 / Windows 98 / Windows NT4 (いずれもサポート提供終了) は、別途ダウンロードすることで使用することができます。

Windows Management Instrumentation (WMI) CORE 1.5 (Windows 95/98/NT 4.0) ★ サポート終了してます。参考情報です!
https://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=afe41f46-e213-4cbf-9c5b-fbf236e0e875

WMI はその名の通り、Windows OS の管理などを行うインターフェースの一種みたいなものであり、ローカル コンピュータおよび適切な権限があればリモート コンピュータの管理もできちゃいます。プリンタのアクセス権を変えたり、Hyper-V の VM を作ったり、その気になれば強制シャットダウンまでもできちゃうくらい強力なのです。
WMIC や WBEMTEST などの OS 付属コマンドの他、公開されたクラスを使ってスクリプトやプログラムを作ることもできます。(VBScript など、Windows Script Host や PowerShell などのスクリプト言語の他、C++ でも、.NET アプリケーションでは System.Management 名前空間から使用することができます。まあ、PowerShell は .NET Framework ベースですが…。)
WMI は Distributed Management Task Force (DMTF) と呼ばれるところが制定している "Web-Based Enterprise Management (WBEMTEST の WBEM)" と "Common Information Model" を Windows で使えるように弊社が実装したものです。WMI を使ったことがある方は、良く "root\cimv2" とでてきて、CIM ってなによ?と思った方もいらっしゃるのではないでしょうか。CIM こそ "Common Information Model" のことだったんですね。

CIM スキーマは DMTF のページから確認することが出来ます。でもふだんここは見る必要があることはあまりないかと思います。自分でクラスを拡張するとかでもない限り…。

Join DMTF at the 2010 Microsoft Management Summit
https://www.dmtf.org/home

ご参考までに。

さて、本題のトラブルシュートネタに入ってみましょう。

WMI は実は結構複雑な仕組みで動作している=問題の切り分けも単純にはいかない
WMI は、以前もちょっと触れましたように、スクリプトだけ動かしている場合はあまり意識しないと思いますが、実は様々な機能や複数のプログラムを跨って一連の処理が実施されます。そのため、「なんか変なエラーが返ってきた!」と言った場合を解決するには、恐らく使用者が思う以上に複雑な切り分けを実施する必要があることに注意が必要です。

image_4[1] 

図 : リモートで WMI を実行する流れはこれだけのプロセスを経る

簡単にできることだから、簡単なしくみであると考えるべきではありません。 複雑なプロセスを経て、単純な動作に見せかけているにすぎないことを心にとどめておくべきなのです。

問題発生時、本当に大雑把に考えるべきことを書き連ねてみましょう。

・自分のスクリプトなど、実装の仕方に問題があるか
・(リモートの場合) そもそも相手側まで到達しているか
・実行したい処理に見合ったアクセス権を与えているか(ユーザ偽装、プロセスアカウントのアクセス権など)
・WMI の動作基盤自体が正常なのか
・WMI のサービス側で発生しているのか
・WMI の処理を許さないグループ / ローカル ポリシーなどが設定されていないか

…などなど。考えることいっぱいありますね。でも、これは本当に大雑把な、ざっくりしているものなのです。
実際にトラブルシュートを行うならば、もっと細かく可能性をつぶして問題点を確定させなくてはいけません。

トラブルシュート時のチェックリスト
たいていの WMI のケースの問題の発端は、クライアント側 (WMI のクラスを呼び出す側)でなんか変だな?と使用者が気づくことです。
私たちサポートに来た時には、「すでに事後となり原因が判らないが何だか問題が起こってしまっている」ということがほとんどです。ほぼすべてのケースに共通する問題解決の最初のステップは、「クライアント側のプログラムに問題があるのか」あるいは「WMI がホストしているプロバイダ」なのか「WMI サービス自身に問題があるのか」を見極めることです。
ちなみに、弊社サポートでは、WMI の動作基盤のチームと、WMI のスクリプトの組み方などの問題解決をする二つのチームがあります。私たちは後者のチームであり、調査の過程で WMI の動作基盤で問題が起きている、すなわちコードの実装などに依存しない問題であると判ったら WMI の動作基盤チームにて対応を依頼することもあります。

さて、ではクライアントなのか、プロバイダなのか、WMI サービスなのか。これらをどうやって確認していくか?
そこを見てみましょう。

(1) WMI のテストをしよう
- ローカル コンピュータ上での問題の場合
最初に、プログラムやコマンドを動作させているローカル コンピュータ上で WMI がきちんと動作しているかを確認します。
- リモートの処理がうまくいかない場合
まず接続先のコンピュータ上で目的の処理が出来るか確認することを実施します。接続先のローカル WMI が動作することが確保できたら、今度はリモート コンピュータの WMI サービスに接続できるか確認するということになります。

-a. ローカルの WMI のサービスを検証する
一番手っ取り早く WMI のサービスを検証するのは、WMIMGNT.msc を使うのをお勧めします。

1. [スタート] メニューから [ファイル名を指定して実行] を選択します。
2. WMIMGMT.msc と記入して [OK] を押します。
3. [WMI コントロール (ローカル)] を右クリックし、[プロパティ(R)] を選択します。   
4. WMI のサービスがきちんと構成されていれば、WMI のサービスに接続している旨のダイアログ(砂時計つき)が表示され、しばらくして WMI コントロールのプロパティを表示させることが出来ます。

image

image ← Windows 7 の例

[全般] タブで OS や WMI のバージョンを見ることができます。もしこの情報が正常そうであれば、ローカルの WMI のサービスの構成状態自体は良好と思ってよいです。
なお、Windows XP や Windows Server 2003 の場合は WMI のバージョンと、OS のビルドバージョンは基本的に一致します。

無題 ← Windows XP の例
Windows XP 以降であれば、OS のビルドは、WMIC コマンドを使っても取ることができます。

wmic OS get Caption,BuildNumber

image

↑Windows XP の場合

image

↑Windows 7 の場合

-b. リモートの WMI のサービスを検証する
まずは -a. を試してみて、どうもローカルはイケてる、でもリモートのマシンに対しての処理がどうもうまくいかないようだという状況だとします。こうした場合、次に試すべきなのは「リモート コンピュータ上の WMI サービスに接続できるか」です。具体的には -a. を応用します。 要は、「リモートマシンの WMI のプロパティが見られりゃ接続はきちんとできているって判断できるってことだろ」ってことです。

1. [スタート] メニューから [ファイル名を指定して実行] を選択します。
2. WMIMGMT.msc と記入して [OK] を押します。
3. [WMI コントロール (ローカル)] を右クリックし、[別のコンピュータに接続(C)...] を選択します。   
4. [管理するコンピュータの変更] ダイアログが開くので、[別のコンピューター(A)] を選択したうえで、リモート管理対象のコンピュータ名を入れます。
5. XP などでは、ここで、WMI サービスに接続する権限のあるユーザ アカウントの資格情報の入力が可能です。変更が必要な場合は、[変更(C)] ボタンを押して適切な権限を持つ資格情報を設定してください。(※)
6. これだけでは確認が不十分ですので、[WMI コントロール (<マシン名など>)]] を右クリックして、[プロパティ(R)] を選択します。   
7. リモートの WMI のサービスに接続が出来ていれば、WMI のサービスに接続している旨のダイアログ(砂時計つき)が表示され、しばらくして WMI コントロールのプロパティを表示させることが出来ます。ちなみに拒否られると、"アクセスが拒否されました" とでてきます。

image

もし、リモートの WMI サービスにアクセスできないのであれば、接続時のプロセスのアカウントが適切であるかを確認します。どうもリモートのプロパティもうまく接続できるぞ、なのにエラーが止まらないという場合は、DCOM の設定を確認します。DCOM の設定については後日の記事で触れる予定です。

(※) なぜか Windows 7 / Vista では [変更(C)]が出てこないかも?ちょっと確認中

-c. スクリプトで動作基盤の状態と、スクリプトが実行できる状態かを見極めてみる
Windows 2000 のビルド 1085 以降、Win32_WMISetting クラスが追加されました。これ以降、ビルドバージョンなど、WMI の設定を見ることが出来ます。
以下のスクリプトは、WMI のサービスの状態およびスクリプトのインターフェース双方の簡単な検証に使用できます。

' <-- コピーここから
set WMI = GetObject("WinMgmts:/root/cimv2")
set obj = WMI.Get("Win32_WMISetting=@")
WScript.Echo obj.GetObjectText_(0)

set objs = WMI.InstancesOf("Win32_OperatingSystem")
for each obj in objs
WScript.Echo obj.GetObjectText_
next

' <-- コピーここまで

上記をコピーして、メモ帳などに張り付け、拡張子 vbs などで保存してください。
その後、コマンドプロンプトを起動し、保存したディレクトリに移動して、CScript や WScript などで保存した vbs ファイルを実行します。

そうするとなんか色々ばーっと出てきます。もし上記 -a. からの検証を実施してきて、このスクリプトで何も情報が出てこないならば、スクリプト関連で何らかの問題を生じている可能性があります。

以下は実際にやってみた例です。長い!

image

********************

さて、本日は以上です。
また磁界をお楽しみに…。

ういこう@明日は花見だ朝早い