このページの本文へ

Windows Info 第410回

WindowsでのDeviceIDの仕組み その2 USBデバイスの親子関係を表示させる

2023年12月17日 10時00分更新

文● 塩田紳二 編集● ASCII

  • この記事をはてなブックマークに追加
  • 本文印刷

 前回は、Windowsのデバイスが持つDeviceIDについて簡単に解説した。今回は、これを利用してUSBデバイスの親子関係を表示させてみる。

USBデバイスのリストを作る

 前回解説したように、Windowsのデバイスは、PowerShellのGet-CimInstanceコマンドを使って列挙することができる。

 各デバイスのDeviceIDは、レジストリのパスの一部になっているため、これを使って、レジストリの情報とコマンドの情報を組み合わせてみる。まずはUSBデバイスのリストを作る。このとき、BluetoothコントローラーがUSB接続だとコントローラーや以下のBluetoothデバイス(プロファイル)などが同時に列挙されてしまうので、これを省く。

$USB=(Get-CimInstance Win32_USBControllerDevice).Dependent.DeviceID | ? {$_ -notlike "BTH*"} | ? {$_ -notlike "SWD*"}

WindowsでのDeviceIDの仕組み

コマンドを使って、変数に処理したいデバイスのリストを記憶させる。ここでは、USBデバイスに限定したが、フィルタ部分(|? DeviceID -in $USB)を外せば、全デバイスを対象に処理を進めることができる

 次に、以下のこれを使って全デバイス(Win32_PnPEntity)の中からUSBデバイスだけを抜き出し、レジストリ情報を追加する。

$mydev=Get-CimInstance Win32_PnPEntity |? DeviceID -in $USB | %{ $p=@{};
  $x=(Join-Path "HKLM:\SYSTEM\CurrentControlSet\Enum" $_.DeviceID | Get-ItemProperty) ;
  foreach($y in $x.psobject.Properties.name ){ $p[$y]=$x.$y };
  Add-Member -InputObject $_ -NotePropertyMembers $p -ErrorAction SilentlyContinue -PassThru }

 最初の部分で全デバイスを列挙(Get-CimInstance Win32_PnPEntity)し、USBデバイスだけを取り出す(? DeviceID -in $USB)。そこからレジストリのパスを作り(Join-Pathコマンド)、レジストリキーのプロパティ(名前、データの組)を取り出す。これはPowerShellのオブジェクトになっているので、ハッシュテーブルに変換(foreach)して、まとめて各デバイスにプロパティとして追加(Add-Member)している。

 なお、USBデバイスのみに限定しているWhere-Objectの部分を外すと、Windowsのデバイス全体が$mydevに記録されるが、後述のプログラムはこれを処理することもできる。

 これでレジストリにある親を示すParentIDPrefixがプロパティとして追加されたので、ここから親子関係を処理する。その前に、$mydevの各デバイスに、子デバイスを格納するためのchildプロパティを追加しておく。

$mydev | Add-Member -NotePropertyName 'Child' -NotePropertyValue @()

 PowerShellは、存在しないプロパティをアクセスするとヌル($null)を返す。コマンドとして使うときには、存在しないこともあるプロパティをアクセスしてもエラーにならないので便利なことが多いが、プロパティの中身がヌルなのか、プロパティ自体が存在しないのかを簡単に区別できない。このため、あらかじめすげてのデバイスの情報に子デバイスを入れるためのプロパティを追加しておく。

 処理が再帰的になるため、PowerShellのコマンドラインのみで記述するのが難しい。このため関数を定義した。以下のリストのプログラム(関数)をエディタなどを使って、ファイル(DevTree.ps1)に書き込み、これをPowerShellから読み込む(コマンドラインでファイルを実行する)。

function global:Proc([ref]$devices){
    foreach($devc in $devices.value){ />
            Add-Child -parentDevice ([ref]$devc) -devices $devices ;
    }
}
function global:Add-Child([ref]$parentDevice,[ref]$devices){
    if ($parentDevice.value.ParentIDPrefix -ne $null) {
        $childList = $devices.value | ? {$_.DeviceID -like "*$($parentDevice.value.ParentIDPrefix)*"}
        foreach ($currentDev in $childList){
            add-child -parentDevice ([ref]$currentDev) -devices $devices
            $parentDevice.value.child += $currentDev
            $devices.value = $devices.value | ? { $_.DeviceID -ne $currentDev.DeviceID }
        }
    }
}
function global:Out-Child($numberOfLevel,$devs,$displayScriptBlock){
    foreach($dev in $devs){
        & $displayScriptBlock $numberOfLevel $dev
        if($dev.child.length -ne 0){
            out-child ($numberOfLevel+1) $dev.child $displayScriptBlock
        }
    }
}

 なお、プログラムは、githubの以下のリポジトリに置いてある(https://github.com/ShinjiShioda/DevTree)。

 これ以降の以下のコマンドは、リストの関数が定義されていることが前提になる。

 Proc関数で最初に$mydevを処理する。このとき、以下のコマンドラインを使う。

Proc ([ref]$mydev)

 Proc関数は、すべてのトップレベルのデバイス(親を持たないデバイス)を処理し、Add-Child関数は、各デバイスの子デバイスを見つける。このAdd-Child関数を再帰的に適用していくことで、子デバイスに孫デバイスを追加していく。これにより、$mydevに親子の構造が作られる。

 このコマンドは関数内で$mydevを書き換えることを可能にするため、引数を「参照渡し」に強制する。それが「“[ref]”キーワード」だが、実行時にキーワードを付けて引数を渡す。このとき、必ず“[ref]”を付けた部分をカッコで囲まないとエラーになってしまう。

 なお、$mydevを保存しておきたい場合、単純なコピーやClone()メソッドは使えない。PowerShellでは、変数には、オブジェクトの参照(ポインタ)だけが入っており、単純な変数同士の代入では、コピーが作られない。Clone()メソッドがするのは「浅いコピー」(Shallow Copy)と言われるもので、一番外側のオブジェクト(この場合は、各デバイスを表すオブジェクトの配列)だけがコピーされるため、これも使えない。これらの場合、他の変数にコピーしても、要素を書き換えると、元のオブジェクトが書き換えられてしまう。

 オブジェクトの完全なコピーである「深いコピー」(Deep Copy)を作るには、一回CSVに変換して戻す。具体的には、以下のコマンドを使う。

$saveDev=$mydev | ConvertTo-Csv | ConvertFrom-Csv

 これで、$mydevを変更しても$saveDevは変化しない。

親子関係を表示する

 この状態で、親デバイスは、Childプロパティに子デバイス(の配列)を持つ。ただし、子デバイスも子デバイス(親から見ると孫デバイス)を持っていることがあり、さらに曾孫(ひまご)、玄孫(やしゃご)……が存在する可能性がある。なので、表示する場合にも再帰的な処理が必要になる。それをするのが「Out-Child」コマンドである。

WindowsでのDeviceIDの仕組み

処理した結果を表示させたところ。ここでは、USBデバイス名のみ表示したが、ダブルクオートの中に「$($dev.DeviceID)」などを挿入すると、DeviceIDも表示できるようになる。ただし、ParentIDPrefixだけではUSBデバイスの親子関係(接続関係)を完全に解決することはできなかった

 さまざまな利用を考え、デバイスの表示方法をスクリプトブロックで渡すことにした。とりあえず、階層構造をインデントで表し、デバイス名を表示するなら、

Out-child 0 $mydev { param($n,$dev); Write-host "$(' '*$n)$($dev.name)" }

とする。この場合、子デバイスは、スペース2つ分インデントして表示される。それが「$(' '*$n)」の部分であり、デバイス名の表示が「$($dev.name)」の部分である。

 レジストリ情報を元に親子関係を調べてみたが、いくつか親がわからないUSBデバイスがある。Windowsのデバイスマネージャーでは、親子関係がきちんと解決されている。おそらく他の情報も併用して親子関係を解決していると思われる。

 今回はParentIDPrefixのみで親子関係を見たが、USBデバイスの接続位置(ハブ番号とポート番号)を記述するLocationInformationという情報もある(ただし、すべてのUSBデバイスがこの情報を持っているわけではない)。これを使うことで、少なくとも親に当たるUSBハブを探すことはできるだろう。とはいえ、プログラムは、作り出すと、満足するまでやめられないのがプログラマの性。いつまでも書き換えていると記事にならないので、ここまでで止めておく。

カテゴリートップへ

この連載の記事

ASCII倶楽部

注目ニュース

  • 角川アスキー総合研究所

プレミアム実機レビュー

ピックアップ
1
Anker PowerLine III Flow USB-C & USB-C ケーブル Anker絡まないケーブル 240W 結束バンド付き USB PD対応 シリコン素材採用 iPhone 17 / 16 / 15 / Galaxy iPad Pro MacBook Pro/Air 各種対応 (1.8m ミッドナイトブラック)
Anker PowerLine III Flow USB-C & USB-C ケーブル Anker絡まないケーブル 240W 結束バンド付き USB PD対応 シリコン素材採用 iPhone 17 / 16 / 15 / Galaxy iPad Pro MacBook Pro/Air 各種対応 (1.8m ミッドナイトブラック)
¥1,390
2
Anker USB Type C ケーブル PowerLine USB-C & USB-A 3.0 ケーブル iPhone 17 / 16 / 15 /Xperia/Galaxy/LG/iPad Pro/MacBook その他 Android 等 USB-C機器対応 テレワーク リモート 在宅勤務 0.9m ホワイト
Anker USB Type C ケーブル PowerLine USB-C & USB-A 3.0 ケーブル iPhone 17 / 16 / 15 /Xperia/Galaxy/LG/iPad Pro/MacBook その他 Android 等 USB-C機器対応 テレワーク リモート 在宅勤務 0.9m ホワイト
¥660
3
KIOXIA(キオクシア)【日本製】USBフラッシュメモリ 32GB USB2.0 国内サポート正規品 KLU202A032GL
KIOXIA(キオクシア)【日本製】USBフラッシュメモリ 32GB USB2.0 国内サポート正規品 KLU202A032GL
¥980
4
【Amazon.co.jp限定】 ロジクール 静音 ワイヤレス トラックボール マウス M575SPd Bluetooth Logibolt 無線 windows mac iPad OS Chrome トラックボールマウス ブラック M575 M575SP 国内正規品 ※Amazon.co.jp限定 壁紙ダウンロード付き
【Amazon.co.jp限定】 ロジクール 静音 ワイヤレス トラックボール マウス M575SPd Bluetooth Logibolt 無線 windows mac iPad OS Chrome トラックボールマウス ブラック M575 M575SP 国内正規品 ※Amazon.co.jp限定 壁紙ダウンロード付き
¥5,280
5
CIO フラットスパイラルケーブル CtoC 1m (Type-C/USB-C) PD 急速充電 平型 磁石 マグネット吸着 まとまる 充電ケーブル PD 240W データ転送 480Mbps (ライトブラック, 1m)
CIO フラットスパイラルケーブル CtoC 1m (Type-C/USB-C) PD 急速充電 平型 磁石 マグネット吸着 まとまる 充電ケーブル PD 240W データ転送 480Mbps (ライトブラック, 1m)
¥1,780
6
Amazon Kindle Paperwhite (16GB) 7インチディスプレイ、色調調節ライト、12週間持続バッテリー、広告なし、ブラック
Amazon Kindle Paperwhite (16GB) 7インチディスプレイ、色調調節ライト、12週間持続バッテリー、広告なし、ブラック
¥18,980
7
Anker iPhone充電ケーブル PowerLine II ライトニングケーブル MFi認証 超高耐久 iPhone 14 / 14 Pro Max / 14 Plus / 13 / 13 Pro / 12 / 11 / X/XS/XR / 8 Plus 各種対応 (0.9m ホワイト)
Anker iPhone充電ケーブル PowerLine II ライトニングケーブル MFi認証 超高耐久 iPhone 14 / 14 Pro Max / 14 Plus / 13 / 13 Pro / 12 / 11 / X/XS/XR / 8 Plus 各種対応 (0.9m ホワイト)
¥990
8
エレコム 電源タップ 6個口 3m 雷ガード 個別スイッチ ほこりシャッター付 耐熱 PSE技術基準適合 ブラック T-K6A-2630BK
エレコム 電源タップ 6個口 3m 雷ガード 個別スイッチ ほこりシャッター付 耐熱 PSE技術基準適合 ブラック T-K6A-2630BK
¥1,590
9
Amazon Kindle - 目に優しい、かさばらない、大きな画面で読みやすい、6週間持続バッテリー、6インチディスプレイ電子書籍リーダー、ブラック、16GB、広告なし
Amazon Kindle - 目に優しい、かさばらない、大きな画面で読みやすい、6週間持続バッテリー、6インチディスプレイ電子書籍リーダー、ブラック、16GB、広告なし
¥13,980
10
キヤノン Canon 純正 インクカートリッジ BCI-381(BK/C/M/Y)+380 5色マルチパック BCI-381+380/5MP 長さ:5.3cm 幅:13.9cm 高さ:10.75cm
キヤノン Canon 純正 インクカートリッジ BCI-381(BK/C/M/Y)+380 5色マルチパック BCI-381+380/5MP 長さ:5.3cm 幅:13.9cm 高さ:10.75cm
¥5,645

Amazonのアソシエイトとして、ASCII.jpは適格販売により収入を得ています。

デジタル用語辞典

ASCII.jpメール デジタルMac/iPodマガジン