もくじ
https://tera1707.com/entry/2022/02/06/144447
やりたいこと
前回、PCに接続されているデバイスを全部取得して表示するということをした。
今回、デバマネの「デバイス(接続別)」と同じように、接続をツリー上に表示するようなコードにしたい。
コード(ほぼby copilot)
今回も、ほぼcopilotに書いてもらった。
一度、うまく動かない部分があったので、そこは手で修正した。
#include <windows.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <locale>
#include <clocale>
#include <shlobj.h> // デスクトップパス取得用
#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "cfgmgr32.lib")
#pragma comment(lib, "shell32.lib")
// 指定したDevInstのFriendlyNameまたはDeviceDescを取得
std::wstring GetDeviceFriendlyName(HDEVINFO hDevInfo, SP_DEVINFO_DATA& devInfoData) {
WCHAR buffer[256];
DWORD requiredSize = 0;
if (SetupDiGetDeviceRegistryPropertyW(
hDevInfo,
&devInfoData,
SPDRP_FRIENDLYNAME,
nullptr,
(PBYTE)buffer,
sizeof(buffer),
&requiredSize
)) {
return buffer;
}
// FriendlyNameがない場合はDeviceDesc
if (SetupDiGetDeviceRegistryPropertyW(
hDevInfo,
&devInfoData,
SPDRP_DEVICEDESC,
nullptr,
(PBYTE)buffer,
sizeof(buffer),
&requiredSize
)) {
return buffer;
}
return L"(取得不可)";
}
// デバイスツリーを再帰的に表示(ファイル出力)
void PrintDeviceTree(HDEVINFO hDevInfo, DEVINST devInst, std::wofstream& ofs, int depth = 0) {
SP_DEVINFO_DATA devInfoData = {};
ULONG status = 0, problem = 0;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
auto a = CM_Get_DevNode_Status(&status, &problem, devInst, 0);
if (a == CR_SUCCESS) {
// Device Instance ID取得
WCHAR deviceId[MAX_DEVICE_ID_LEN];
if (CM_Get_Device_IDW(devInst, deviceId, MAX_DEVICE_ID_LEN, 0) != CR_SUCCESS) {
wcscpy_s(deviceId, L"(取得失敗)");
}
// SP_DEVINFO_DATAを取得
DWORD index = 0;
bool found = false;
while (SetupDiEnumDeviceInfo(hDevInfo, index, &devInfoData)) {
++index;
WCHAR tmpId[MAX_DEVICE_ID_LEN];
if (CM_Get_Device_IDW(devInfoData.DevInst, tmpId, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS) {
if (wcscmp(tmpId, deviceId) == 0) {
found = true;
break;
}
}
}
// インデント
for (int i = 0; i < depth; ++i) ofs << L" ";
ofs << L"[" << deviceId << L"] ";
if (found) {
ofs << GetDeviceFriendlyName(hDevInfo, devInfoData);
}
else {
ofs << L"(FriendlyName取得不可)";
}
ofs << std::endl;
}
// 子デバイスを再帰的に表示
DEVINST childDevInst;
if (CM_Get_Child(&childDevInst, devInst, 0) == CR_SUCCESS) {
PrintDeviceTree(hDevInfo, childDevInst, ofs, depth + 1);
// 兄弟デバイスをたどる
DEVINST siblingDevInst = childDevInst;
while (CM_Get_Sibling(&siblingDevInst, siblingDevInst, 0) == CR_SUCCESS) {
PrintDeviceTree(hDevInfo, siblingDevInst, ofs, depth + 1);
}
}
}
int main()
{
std::setlocale(LC_ALL, "ja_JP.UTF-8");
// デスクトップパス取得
WCHAR desktopPath[MAX_PATH];
if (SHGetSpecialFolderPathW(nullptr, desktopPath, CSIDL_DESKTOPDIRECTORY, FALSE) == FALSE) {
std::wcerr << L"デスクトップパスの取得に失敗しました。" << std::endl;
return 1;
}
std::wstring filePath = desktopPath;
filePath += L"\\device_tree.txt";
// ファイル出力ストリームを開く
std::wofstream ofs(filePath);
if (!ofs) {
std::wcerr << L"ファイルの作成に失敗しました: " << filePath << std::endl;
return 1;
}
ofs.imbue(std::locale("ja_JP.UTF-8"));
// すべてのデバイスを取得
HDEVINFO hDevInfo = SetupDiGetClassDevsA(
nullptr, // すべてのクラス
nullptr,
nullptr,
DIGCF_ALLCLASSES | DIGCF_PRESENT
);
if (hDevInfo == INVALID_HANDLE_VALUE) {
ofs << L"SetupDiGetClassDevsA failed." << std::endl;
return 1;
}
// ルートデバイスからツリー表示
DEVINST rootDevInst;
if (CM_Locate_DevNodeW(&rootDevInst, nullptr, 0) == CR_SUCCESS) {
PrintDeviceTree(hDevInfo, rootDevInst, ofs, 0);
}
else {
ofs << L"ルートデバイスの取得に失敗しました。" << std::endl;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
ofs.close();
return 0;
}
動かして吐いたテキストファイル
こんな感じで出力された。
[HTREE\ROOT\0] (取得不可)
[ROOT\JUNGO\0000] WinDriver
[ROOT\VOLMGR\0000] ボリューム マネージャー
[STORAGE\VOLUME\{9504634E-A3D5-11EC-89DE-806E6F6E6963}#0000000000004400] ボリューム
[STORAGE\VOLUME\{9504634E-A3D5-11EC-89DE-806E6F6E6963}#0000000008100000] ボリューム
[STORAGE\VOLUME\{9504634E-A3D5-11EC-89DE-806E6F6E6963}#000000000E500000] ボリューム
[STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT1] 汎用ボリューム シャドウ コピー
[STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT2] 汎用ボリューム シャドウ コピー
[STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT3] 汎用ボリューム シャドウ コピー
[STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT4] 汎用ボリューム シャドウ コピー
[STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT5] 汎用ボリューム シャドウ コピー
[STORAGE\VOLUME\{9504634E-A3D5-11EC-89DE-806E6F6E6963}#000000E7C2000000] ボリューム
[STORAGE\VOLUME\{9504634E-A3D5-11EC-89DE-806E6F6E6963}#000000E7EF200000] ボリューム
[ROOT\VMBUS\0000] Microsoft Hyper-V Virtual Machine Bus Provider
[ROOT\BASICDISPLAY\0000] Microsoft 基本ディスプレイ ドライバー
[ROOT\HVSERVICE\0000] Microsoft ハイパーバイザー サービス
[ROOT\NET\0000] Fortinet Virtual Ethernet Adapter (NDIS 6.30)
[ROOT\NET\0001] Fortinet SSL VPN Virtual Ethernet Adapter
[ROOT\NET\0002] PPPoP WAN Adapter
[ROOT\VID\0000] Microsoft Hyper-V 仮想化インフラストラクチャ ドライバー
[ROOT\COMPOSITEBUS\0000] 複合バス列挙子
[ROOT\VDRVROOT\0000] Microsoft 仮想ドライブ列挙子
[ROOT\SPACEPORT\0000] Microsoft 記憶域コントローラー
[ROOT\KDNIC\0000] Microsoft Kernel Debug Network Adapter #2
[ROOT\UMBUS\0000] UMBus Root Bus Enumerator
[UMB\UMB\1&841921D&0&TERMINPUT_BUS] UMBus Enumerator
[ROOT\ACPI_HAL\0000] ACPI x64 ベース PC
[ACPI_HAL\PNP0C08\0] Microsoft ACPI-Compliant System
[ACPI\PNP0A08\0] PCI Express ルート コンプレックス
[PCI\VEN_8086&DEV_9B63&SUBSYS_86941043&REV_03\3&11583659&0&00] PCI 標準ホスト CPU ブリッジ
[PCI\VEN_8086&DEV_9BC8&SUBSYS_86941043&REV_03\3&11583659&0&10] Intel(R) UHD Graphics 630
[SWD\DRIVERENUM\CUI&4&18929383&0] Intel(R) Graphics Control Panel
[SWD\DRIVERENUM\IGCC&4&18929383&0] Intel(R) Graphics Command Center
[DISPLAY\DEL42A2\4&18929383&0&UID200195] Dell P3223QE (DP)
[PCI\VEN_8086&DEV_43ED&SUBSYS_86941043&REV_11\3&11583659&0&A0] Intel(R) USB 3.20 eXtensible Host Controller - 1.20 (Microsoft)
[USB\ROOT_HUB30\4&1C1E67E3&0&0] USB ルート ハブ (USB 3.0)
[USB\VID_0A12&PID_0001\5&153678D8&0&4] Generic Bluetooth Radio
[BTH\MS_RFCOMM\6&190A23EC&0&0] Bluetooth Device (RFCOMM Protocol TDI)
[BTH\MS_BTHBRB\6&190A23EC&0&1] Microsoft Bluetooth Enumerator
[BTHENUM\{00000000-DECA-FADE-DECA-DEAFDECACAFE}_VID&0001004C_PID&740F\7&281E3D1F&0&B456E38ACECE_C00000000] Bluetooth 周辺デバイス
[BTHENUM\{00001000-0000-1000-8000-00805F9B34FB}_VID&0001004C_PID&740F\7&281E3D1F&0&B456E38ACECE_C00000000] サービス検索サービス
[BTHENUM\{0000110A-0000-1000-8000-00805F9B34FB}_VID&0001004C_PID&740F\7&281E3D1F&0&B456E38ACECE_C00000000] iPhone A2DP SNK
[BTHENUM\{0000110B-0000-1000-8000-00805F9B34FB}_LOCALMFG&000A\7&281E3D1F&0&0CA694033D59_C00000000] HK Onyx Studio
[SWD\MMDEVAPI\{0.0.0.00000000}.{427A9F29-10B4-4302-A7B1-F6D4EE64CD7F}] スピーカー (3- HK Onyx Studio)
[BTHENUM\{0000110C-0000-1000-8000-00805F9B34FB}_LOCALMFG&000A\7&281E3D1F&0&0CA694033D59_C00000000] HK Onyx Studio Avrcp トランスポート
[BTHENUM\{0000110C-0000-1000-8000-00805F9B34FB}_VID&0001004C_PID&740F\7&281E3D1F&0&B456E38ACECE_C00000000] iPhone Avrcp トランスポート
・
・
・
・
・

