【VBS】HDD情報を取得する

# はじめに
これは、[Visual Basic Advent Calendar 2017](https://qiita.com/advent-calendar/2017/vb)の12/18日の記事となります。

NASサーバーの調子が悪くなり交換しようとした際、会社の推奨品一覧にはNASサーバーの型番の記載がなく、カートリッジの型番しか載っていないということがありました。

コントロールパネルのデバイスマネージャーで型番が分かるものがありますが、分からないもの(別名になっている)もあるようです。
[バッファローの外付けHDDのメーカを実際に確認するには、どうすればよいのでしょうか。](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1332944468)

そのような場合、「[CrystalDiskInfo](https://crystalmark.info/software/CrystalDiskInfo/)」というソフトを使えば情報が取れるようですが、フリーソフトをインストールできない環境もありえます。

ということで、HDD情報を取得するスクリプトを作成しました。

# HDD情報の取得
スクリプトの出力結果は次のようになります。

```bat:出力結果
メーカー: BUFFALO INC.
モデル: WS5000R2 シリーズ

ドライブ:C:
HDDの型番: IDE
モデル: ST1000DM003-1ER162
サイズ: 1000 GB
状態: OK

ドライブ:D:
HDDの型番: IDE
モデル: ST1000DM003-1ER162
サイズ: 1000 GB
状態: OK
```

# ソースコード
```vb:HDD情報取得.vbs
Option Explicit

Dim InfoStr

' メーカー、モデル情報の取得
GetSystemInfo InfoStr
' 物理ドライブ情報の取得
GetDrivesInfoByType InfoStr 

WScript.Echo InfoStr

'---------------------------------------------
' メーカー、モデル情報の取得
'---------------------------------------------
Function GetSystemInfo(ByRef Str) 
    Dim oLocator
    Dim oService
    Dim oClassSet
    Dim oClass
    Dim objShell
    Dim strComputer
    Dim strValue
    Dim makerName
    Dim modelName
    Dim objRegistry
    Dim strKeyPath
    Dim strValueName

    const HKEY_LOCAL_MACHINE = &H80000002

    GetSystemInfo = False

    'メーカー、モデルの取得
    Set oLocator = Wscript.CreateObject("WbemScripting.SWbemLocator")
    Set oService = oLocator.ConnectServer
    'クエリー条件を WQL にて指定する。
    Set oClassSet = oService.ExecQuery("Select * From Win32_ComputerSystem")

    'コレクションを解析する。
    For Each oClass In oClassSet
        makerName = oClass.Manufacturer
        modelName = oClass.Model
    Next

    strComputer = "."

    Set objShell = WScript.CreateObject("WScript.Shell")
    Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv") 
    strKeyPath = "Software\Microsoft\Windows\CurrentVersion\OEMInformation" 
    strValueName = "Manufacturer" 
    objRegistry.GetStringValue HKEY_LOCAL_MACHINE , strKeyPath, strValueName , strValue 
    If Not IsNull(strValue) Then 
        makerName = objShell.RegRead("HKEY_LOCAL_MACHINE\" & strKeyPath & "\" & strValueName)
    End If
     
    strValueName = "Model" 
    objRegistry.GetStringValue HKEY_LOCAL_MACHINE , strKeyPath, strValueName , strValue 
    If Not IsNull(strValue) Then 
        modelName = objShell.RegRead("HKEY_LOCAL_MACHINE\" & strKeyPath & "\" & strValueName)
    End If

    Str = Str & "メーカー: " & makerName & vbCrLf & _
                "モデル: " & modelName & vbCrLf & vbCrLf

    Set oLocator = Nothing
    Set oService = Nothing
    Set oClassSet = Nothing
    Set objShell = Nothing

    GetSystemInfo = True

End Function

'---------------------------------------------
' 物理ドライブ情報の取得
'---------------------------------------------
Function GetDrivesInfoByType(ByRef Str) 
    Dim strComputer
    Dim objWMIService
    Dim DiskDrives
    Dim DiskDrive
    Dim strDeviceID
    Dim Query
    Dim DiskPartitions
    Dim DiskPartition
    Dim LogicalDisks
    Dim LogicalDisk
    Dim colDiskDrives
    Dim objDiskDrive

    GetDrivesInfoByType = False

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

    Query="SELECT * FROM Win32_DiskDrive"
    Set DiskDrives = objWMIService.ExecQuery(Query)

    For Each DiskDrive in DiskDrives 
       strDeviceID = Replace(DiskDrive.DeviceID, "\", "\\")
       Query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & strDeviceID
       Query = Query & """} WHERE AssocClass=Win32_DiskDriveToDiskPartition"
       Set DiskPartitions = objWMIService.ExecQuery(Query) 

       For Each DiskPartition in DiskPartitions
           Query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & DiskPartition.DeviceID
           Query = Query & """} WHERE AssocClass=Win32_LogicalDiskToPartition"
           Set LogicalDisks = objWMIService.ExecQuery(Query)

           For Each LogicalDisk In LogicalDisks
               LinesAdd Str, "ドライブ:" & LogicalDisk.DeviceID
               Query = "Select * from Win32_DiskDrive WHERE DeviceID = '" & strDeviceID & "'"
               Set colDiskDrives = objWMIService.ExecQuery(Query)
               For Each objDiskDrive in colDiskDrives
                   LinesAdd Str, "HDDの型番: " & objDiskDrive.InterfaceType
                   LinesAdd Str, "モデル: " & objDiskDrive.Model
                   LinesAdd Str, "サイズ: " & Int(objDiskDrive.Size/1000000000) & " GB"
                   LinesAdd Str, "状態: " & objDiskDrive.Status
                   LinesAdd Str, ""
               Next 
               GetDrivesInfoByType = True
           Next 
           Set LogicalDisks = Nothing

        Next 
        Set DiskPartitions = Nothing

        Exit For
    Next

    Set DiskDrives = Nothing
    Set objWMIService = Nothing

End Function

Sub LinesAdd(ByRef S, V)
    S = S & V & vbNewLine
End Sub
```

# ライセンスっぽいこと
コード改変や配布は自由です。
このツールによる義務／責任を何ら負いません。

# 最後に
かなり前に作成して1回しか使われなかったけど、誰かに役に立てばいいと思います。