あるデバイスが今WindowsPCにつながってるかどうかを調べる

tera1707.com

やりたいこと

バイスマネージャーのデバイスの一覧の中に、特定のデバイスがあるかどうかを探したい。まずは、デバイスマネージャーに出てくる項目を一覧したい。

やり方

やる前メモ

現状、この辺のデバイスがどういう仕組みで動いてるとか、デバイスマネージャに出てきている項目がなんなのか(つながってるデバイスが出てきてるのか、つながってないけどドライバ入ってたら出てきてるのか、そもそもドライバって何なのか?)がわかってないので、やっていることがふわふわしていて自信がないのだが、現状調べたことを忘れる前にメモしようと思う。

やる

下記関数を使う。

  • SetupDiGetClassDevs()
  • SetupDiEnumDeviceInfo()
  • SetupDiGetDeviceRegistryProperty()

サンプルコード

ということをする。

#include <stdio.h>
#include <windows.h>
#include <setupapi.h>
#include <iostream>
#include <combaseapi.h>

#pragma comment(lib, "setupapi.lib")

int main()
{
    std::wcout.imbue(std::locale(""));//std::wcoutのためのおまじない(これないとConsoleに文字でない)

    DWORD dwIndex;
    TCHAR* pszName;
    DWORD dwSize;
    DWORD dwRegType;
    BOOL bRet;
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA sDevInfo;

    hDevInfo = ::SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES);
    if (hDevInfo == INVALID_HANDLE_VALUE)
        return -1;

    dwIndex = 0;
    ::ZeroMemory(&sDevInfo, sizeof(SP_DEVINFO_DATA));
    sDevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
    while (1)
    {
        bRet = ::SetupDiEnumDeviceInfo(hDevInfo, dwIndex++, &sDevInfo);
        if (bRet == FALSE)
            break;

        // Property情報をまとめて取る
        int props[] = {
            SPDRP_CLASS,
            SPDRP_CLASSGUID,
            SPDRP_DEVICEDESC,
            SPDRP_DRIVER,
            SPDRP_ENUMERATOR_NAME,
            SPDRP_HARDWAREID,
            SPDRP_MFG,
            SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
            SPDRP_FRIENDLYNAME,
        };

        std::wstring strMessage;// デバイス1個分の出力内容を一時保存

        for (int i = 0; i < sizeof(props)/ sizeof(int); i++)
        {
            // 第三引数(Property)で指定できる、取れる情報の種類は下記参照。
            // https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya#parameters
            // 第五引数をnullにして呼ぶと、必要なバッファのバイト数が取れるので、その分のバッファを用意する
            dwSize = 0;
            bRet = ::SetupDiGetDeviceRegistryProperty(hDevInfo, &sDevInfo, props[i], &dwRegType, NULL, 0, &dwSize);
            pszName = new TCHAR[dwSize];
            if (pszName == NULL)
                break;
            bRet = ::SetupDiGetDeviceRegistryProperty(hDevInfo, &sDevInfo, props[i], &dwRegType, (BYTE*)pszName, dwSize, &dwSize);
            if (bRet != FALSE)
            {
                strMessage += pszName;
                strMessage += TEXT(",");
            }
            delete    pszName;
        }

        std::wcout << strMessage.c_str() << std::endl;
    }

    ::SetupDiDestroyDeviceInfoList(hDevInfo);
    return 0;
}

これで取れたものが下記。(csv) f:id:tera1707:20220220004146p:plain

この情報の中で、ハードウェアID(SPDRP_HARDWAREID)あたりが、全体の中でユニークっぽいので、それを使えば目的のハードウェアがつながってるかどうか調べられそう。

よくわかってないのでしらべてみたいこと

  • 「デバイスインターフェース」とは何?
  • デバマネで、デバイスを有効/無効に切り替えれるが、その有効無効判定はできるか?
  • 今はつながってないけど、ドライバインストールされてるもの、とかも取れるか?

参考

SetupDiGetClassDevs()関数 SetupDiGetClassDevsW function (setupapi.h) - Win32 apps | Microsoft Docs

SetupDiEnumDeviceInfo()関数 SetupDiEnumDeviceInfo function (setupapi.h) - Win32 apps | Microsoft Docs

SetupDiGetDeviceRegistryProperty()関数のページ。取れる情報の種類。SPDRP_DEVICEDESCとか。

SetupDiGetDeviceRegistryPropertyA function (setupapi.h) - Win32 apps | Microsoft Docs

C++/windowsでデバイスの情報を取ったりする参考になるやり方がたくさん書かれてる www.usefullcode.net