Hey, Scripting Guy!

Hey, Scripting Guy!

TechNet コラムへようこそ。このコラムでは、よく寄せられるシステム管理スクリプトに関する質問に Scripting Guys がお答えします。システム管理スクリプトについて質問がある場合は、scripter@microsoft.com (英語のみ) までお送りください。すべての質問に回答することはできないかもしれませんが、可能な限り対応いたします。

今日の質問: 論理ドライブと物理ディスクを相互に関連付ける方法はありますか


論理ドライブと物理ディスクを相互に関連付ける方法はありますか

Q

Scripting Guy さん、よろしくお願いします。論理ドライブと物理ディスクを相互に関連付ける方法はありますか。

-- LB

A

LB さん、こんにちは。それでは取引しましょう。どの論理ドライブがどの物理ディスクにあるのかを示すスクリプトをお教えするので、"ちょっと待った、このスクリプトの動作が理解できない" とは言わないと約束してください。実を言うと、"私たち自身" もスクリプトの動作を理解しているかどうか確信が持てないのです。すぐにわかりますが、このスクリプトは控えめに言っても少し風変わりです。

問題なのは、任意の物理ディスクに関連付けられている論理ディスクを取得する単純でわかりやすい方法がないことです。代わりに、2 つの関連付けクラス (Win32_DiskDriveToDiskPartition と Win32_LogicalDiskToPartition) を使用して、論理ドライブとディスク間の関係を調べる必要があります。この方法でも問題はありませんが、関連付けクラスは非常にわかりにくい場合があり、関連付けクラスを使用するために必要なコードは "それ以上に" わかりにくい場合があります。スクリプトの作成を始めてまだ日が浅い場合は、コードを無理に理解しようとせずに、ただ使用した方がいいかもしれません。

スクリプトは次のとおりです。

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colDiskDrives = objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive")
 
For Each objDrive In colDiskDrives
    Wscript.Echo "Physical Disk: " & objDrive.Caption & " -- " & objDrive.DeviceID 
    strDeviceID = Replace(objDrive.DeviceID, "\", "\\")
    Set colPartitions = objWMIService.ExecQuery _
        ("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & _
            strDeviceID & """} WHERE AssocClass = " & _
                "Win32_DiskDriveToDiskPartition")
 
    For Each objPartition In colPartitions
        Wscript.Echo "Disk Partition: " & objPartition.DeviceID
        Set colLogicalDisks = objWMIService.ExecQuery _
            ("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & _
                objPartition.DeviceID & """} WHERE AssocClass = " & _
                    "Win32_LogicalDiskToPartition")
 
        For Each objLogicalDisk In colLogicalDisks
            Wscript.Echo "Logical Disk: " & objLogicalDisk.DeviceID
        Next
        Wscript.Echo
    Next
    Wscript.Echo
Next

風変わりだと言いましたよね。実際には、最初はそれほど変わってはいません。単純に WMI サービスに接続し、ExecQuery メソッドを使用して、コンピュータにインストールされているすべての物理ディスク ドライブのコレクションを取得します。次に、For Each ループを作成してディスク ドライブのコレクションをループし、Caption プロパティと DeviceID プロパティの値をエコーします。

さて、ここからが少し厄介になります。各ディスク ドライブを一意に識別する DeviceID の値は、\\.\PHYSICALDRIVE0 のようになります。この値をクエリで使用するので、各 \ を 2 つ目の \ で "エスケープ" する必要があります (その理由は、\ が WMI の予約文字であるためです)。次のコードで、この処理を行っています。

strDeviceID = Replace(objDrive.DeviceID, "\", "\\")

処理を行ったら、このクエリを使用して、コンピュータ上の最初の物理ディスク ドライブに関連付けられているすべてのディスク パーティションを返すことができます。

Set colPartitions = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & _
        strDeviceID & """} WHERE AssocClass = " & _
            "Win32_DiskDriveToDiskPartition")

意外かもしれませんが、ここまで順調に進んでいます。最初のドライブにあるすべてのディスク パーティションのコレクションは取得できました。パーティションを取得できたので、2 つ目の For Each ループをセット アップして、これらのパーティションを繰り返し処理します。その後、コレクション内の各パーティションについて、次のクエリを使用してパーティションにあるすべての論理ドライブを取得します。

Set colLogicalDisks = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & _
        objPartition.DeviceID & """} WHERE AssocClass = " & _
            "Win32_LogicalDiskToPartition")

後は、最初の物理ディスクの最初のパーティションにあるすべての論理ディスクをエコー バックする 3 つ目の For Each ループをセット アップするだけです。

For Each objLogicalDisk In colLogicalDisks
    Wscript.Echo "Logical Disk: " & objLogicalDisk.DeviceID
Next

ループに戻り、ディスク 1 の残りのパーティションすべてに対して処理を繰り返します。その後、さらにループに戻って、コンピュータ上にある追加のディスク ドライブに対して処理を繰り返します。すべて完了すると、次のようなレポートが返されます。

Physical Disk: IC25N040ATMR04-0 -- \\.\PHYSICALDRIVE0
Disk Partition: Disk #0, Partition #0

Disk Partition: Disk #0, Partition #1
Logical Disk: C:

Disk Parititon: Disk #0, Partition #2
Logical Disk: D:

Physical Disk: Memory Stick Slot -- \\.\PHYSICALDRIVE1

ご覧のとおり、最初のディスクには 3 つのパーティションと、C および D の 2 つの論理ドライブがあります。2 つ目のディスクにはパーティションも論理ドライブもありません (Microsoft が Scripting Guys に 2 つのディスク ドライブを持つコンピュータをくれると思いますか)。

前にも言いましたが、すべてを理解できなくても心配する必要はありません。ホット ドッグの作り方なんてだれも知りませんし、実際のところ知りたいとも思わないでしょう。ただマスタードとピクルスを添えて味わうだけです。このスクリプトについても同じことが言えます (マスタードとピクルスはないかもしれませんが)。


関連情報

Hey, Scripting Guy! - アーカイブもチェックしてください。

ページのトップへページのトップへ