SetupAPIを使ってディスクドライブを列挙する [CodeTips]
前回の記事は8月だったので、約四ヶ月!間が空いてしまいました。
でも、ここは思い出したようにやっていきます。
さて、今回はWindows Setup API を使って、ディスクドライブデバイスを列挙する例です。
この例は、SetupAPIのDevice Installation Function(SetupDiのプリフィクスを持つ)を使って、ディスクドライブクラスに登録されているデバイスを列挙して表示します。
SetupDiGetClassDevsEx関数にGUID_DEVCLASS_DISKDRIVEを指定してディスクドライブのみを列挙する様に指定し、同時にDIGCF_PROFILEを指定して現在のハードウェアプロファイルすべてを列挙する様にしています。
GUID_DEVCLASS_DISKDRIVEは、ディスクドライブ(DiskDrive)クラスを示すGUIDで、そのデバイスの列挙を指示します。一般的には内蔵ハードディスクやUSBの外付けディスク、SDカード、メモリスティックなどや仮想ディスクなども含め「ディスク」として認識され、通常エクスプローラ上でドライブが割り当てられるデバイスを指します。
フラグにDIGCF_PROFILEを指定する(0でも可。その場合はすべてのハードウェアプロファイルが対象になる)と面白い情報を得ることができます。アクティブなディスクデバイス以外に非アクティブなデバイスも列挙することができるのです。このサンプルを実行すると、例えば過去にPCに接続して、その時点でそうはたUSBメモリなども表示されます。私も長期間使っているPCに試したところ、いろいろ懐かしいUSBメモリや今は手元に無いデジカメや携帯プレーヤーなどが表示され感慨深いものがありました。
ただ、この例は対象をディスクデバイスクラスのみとしているため、DVD/CD-ROMドライブやフロッピーディスクなどディスクドライブ以外のクラスに属するデバイスは表示されません(恐らくスマートフォンもポータブルデバイス扱いで表示できません。ただ、モバイルデバイスに詳しくないので判りませんが、ものによってはソフトのインストールの為CD-ROMクラスデバイスを登録する機種ある様です。なので、ディスクドライブで表示するものもあるかもしれません)。しかし、これらのクラスを含めるのは簡単でGUID_DEVCLASS_DISKDRIVEの部分をそれぞれのクラスGUID(GUID_DEVCLASS_CDROMなど)に置き換えれば同じ様に列挙できます(もちろんGUIDを指定せず、すべてのデバイスクラス、デバイスを列挙することも可能です)。デバイスクラスはdevguid.hに記述されています。
SetupDiGetClassDevsEx関数が成功したら、後は返されたHDEVINFO を使ってSetupDiEnumDeviceInfo関数でデバイスを列挙します。デバイス情報がSP_DEVINFO_DATAに返されるので、それを使ってSetupDiGetDeviceProperty関数を呼び出し、デバイスのプロパティを得ます。取得したいプロパティの種類は引数で指定できます。ここでは単純にDEVPKEY_Device_FriendlyNameのみを取得しています。フレンドリ名とはその名の通り人間が読む為のデバイス名や商品名で構成されます。
プロパティには型があるので、一応PropertyTypeに返されるプロパティタイプをチェックし、文字列(DEVPROP_TYPE_STRING)の場合のみ表示しています。このPropertyTypeにはいろいろな型があるので、より多くのプロパティを取得したい場合には、それぞれきちんと確認する必要があります。
SetupDiGetDevicePropertyはWindows Vista以降で登場したAPIなので、Windows XP以前では使えません。もし、Windows XPで実行したい場合はSetupDiGetDevicePropertyの部分を以下の様に書き換えます。
この様にコンフィグレーションマネージャのAPIを使用するため、cfgmgr32.hのインクルードも追加してください。
こうやって多数のデバイスが列挙されたら、不要なものを削除したくなるかもしれません。その様な場合はデバイスマネージャやDeviceWalkerなどで削除すると良いでしょう。
今回、この例の様なフレンドリ名に加え、もう少しだけ表示するプロパティを追加した「完全版」サンプルをGitHubに上げておきました。以下はその一部(mainのみ)です。このサンプルもディスクドライブクラスのみ列挙しています。
すべてのソースコードを以下に載せましたので、興味のある方はどうぞ。
GitHub レポジトリ:
https://github.com/katsu-y/fsstoragedevice
でも、ここは思い出したようにやっていきます。
さて、今回はWindows Setup API を使って、ディスクドライブデバイスを列挙する例です。
#include <stdio.h> #include <windows.h> #include <setupapi.h> #include <devguid.h> #define INITGUID #include <devpkey.h> int wmain(int argc, WCHAR* argv[]) { HDEVINFO hDevInfo; hDevInfo = SetupDiGetClassDevsEx(&GUID_DEVCLASS_DISKDRIVE,NULL,NULL, DIGCF_PROFILE,NULL,NULL,NULL); if( hDevInfo != INVALID_HANDLE_VALUE ) { SP_DEVINFO_DATA DevInfoData = {0}; DevInfoData.cbSize = sizeof(DevInfoData); BYTE Buffer[4096]; DWORD Index = 0; while( SetupDiEnumDeviceInfo(hDevInfo,Index,&DevInfoData) ) { DEVPROPTYPE PropertyType; if( SetupDiGetDeviceProperty(hDevInfo,&DevInfoData, &DEVPKEY_Device_FriendlyName,&PropertyType, Buffer,sizeof(Buffer),NULL,0) ) { if( PropertyType == DEVPROP_TYPE_STRING ) { wprintf(L"%s\n",(PWSTR)Buffer); } } Index++; } SetupDiDestroyDeviceInfoList(hDevInfo); } return 0; } |
この例は、SetupAPIのDevice Installation Function(SetupDiのプリフィクスを持つ)を使って、ディスクドライブクラスに登録されているデバイスを列挙して表示します。
SetupDiGetClassDevsEx関数にGUID_DEVCLASS_DISKDRIVEを指定してディスクドライブのみを列挙する様に指定し、同時にDIGCF_PROFILEを指定して現在のハードウェアプロファイルすべてを列挙する様にしています。
GUID_DEVCLASS_DISKDRIVEは、ディスクドライブ(DiskDrive)クラスを示すGUIDで、そのデバイスの列挙を指示します。一般的には内蔵ハードディスクやUSBの外付けディスク、SDカード、メモリスティックなどや仮想ディスクなども含め「ディスク」として認識され、通常エクスプローラ上でドライブが割り当てられるデバイスを指します。
フラグにDIGCF_PROFILEを指定する(0でも可。その場合はすべてのハードウェアプロファイルが対象になる)と面白い情報を得ることができます。アクティブなディスクデバイス以外に非アクティブなデバイスも列挙することができるのです。このサンプルを実行すると、例えば過去にPCに接続して、その時点でそうはたUSBメモリなども表示されます。私も長期間使っているPCに試したところ、いろいろ懐かしいUSBメモリや今は手元に無いデジカメや携帯プレーヤーなどが表示され感慨深いものがありました。
ただ、この例は対象をディスクデバイスクラスのみとしているため、DVD/CD-ROMドライブやフロッピーディスクなどディスクドライブ以外のクラスに属するデバイスは表示されません(恐らくスマートフォンもポータブルデバイス扱いで表示できません。ただ、モバイルデバイスに詳しくないので判りませんが、ものによってはソフトのインストールの為CD-ROMクラスデバイスを登録する機種ある様です。なので、ディスクドライブで表示するものもあるかもしれません)。しかし、これらのクラスを含めるのは簡単でGUID_DEVCLASS_DISKDRIVEの部分をそれぞれのクラスGUID(GUID_DEVCLASS_CDROMなど)に置き換えれば同じ様に列挙できます(もちろんGUIDを指定せず、すべてのデバイスクラス、デバイスを列挙することも可能です)。デバイスクラスはdevguid.hに記述されています。
SetupDiGetClassDevsEx関数が成功したら、後は返されたHDEVINFO を使ってSetupDiEnumDeviceInfo関数でデバイスを列挙します。デバイス情報がSP_DEVINFO_DATAに返されるので、それを使ってSetupDiGetDeviceProperty関数を呼び出し、デバイスのプロパティを得ます。取得したいプロパティの種類は引数で指定できます。ここでは単純にDEVPKEY_Device_FriendlyNameのみを取得しています。フレンドリ名とはその名の通り人間が読む為のデバイス名や商品名で構成されます。
プロパティには型があるので、一応PropertyTypeに返されるプロパティタイプをチェックし、文字列(DEVPROP_TYPE_STRING)の場合のみ表示しています。このPropertyTypeにはいろいろな型があるので、より多くのプロパティを取得したい場合には、それぞれきちんと確認する必要があります。
SetupDiGetDevicePropertyはWindows Vista以降で登場したAPIなので、Windows XP以前では使えません。もし、Windows XPで実行したい場合はSetupDiGetDevicePropertyの部分を以下の様に書き換えます。
ULONG ulRegDataType; ULONG cbBuffer = sizeof(Buffer); if( CM_Get_DevNode_Registry_Property(DevInfoData.DevInst,CM_DRP_FRIENDLYNAME, &ulRegDataType,Buffer,&cbBuffer,0) == CR_SUCCESS ) { wprintf(L"%s\n",(PWSTR)Buffer); } |
この様にコンフィグレーションマネージャのAPIを使用するため、cfgmgr32.hのインクルードも追加してください。
#include <cfgmgr32.h> |
こうやって多数のデバイスが列挙されたら、不要なものを削除したくなるかもしれません。その様な場合はデバイスマネージャやDeviceWalkerなどで削除すると良いでしょう。
今回、この例の様なフレンドリ名に加え、もう少しだけ表示するプロパティを追加した「完全版」サンプルをGitHubに上げておきました。以下はその一部(mainのみ)です。このサンプルもディスクドライブクラスのみ列挙しています。
int wmain(int /*argc*/, WCHAR* /*argv[]*/) { _wsetlocale(LC_ALL, L""); CSimpleArray |
すべてのソースコードを以下に載せましたので、興味のある方はどうぞ。
GitHub レポジトリ:
https://github.com/katsu-y/fsstoragedevice
2016-12-14 00:20
nice!(0)
コメント(0)
トラックバック(0)
コメント 0