4

WMI を使用して、Windows での USB デバイスの挿入と CD/DVD の挿入を追跡しようとしています。しかし、Win32_LogicalDisk クラスを使用してこれらのイベントを追跡すると、フロッピーがノイズを出し始めます。

私のクエリは以下のようなものです。1 つ目は USB 用で、2 つ目は CD 用です。

q = gcnew WqlEventQuery();
q->EventClassName = "__InstanceCreationEvent";
q->WithinInterval = TimeSpan(0, 0, 3);
q->Condition = "TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 2 and TargetInstance.DeviceID <> 'A:' and TargetInstance.DeviceID <> 'B:'";
w = gcnew ManagementEventWatcher(scope, q);
w->EventArrived += gcnew EventArrivedEventHandler(USBAdded);
w->Start();

q = gcnew WqlEventQuery();
q->EventClassName = "__InstanceModificationEvent";
q->WithinInterval = TimeSpan(0, 0, 3);
q->Condition = "TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5 and TargetInstance.DeviceID <> 'A:' and TargetInstance.DeviceID <> 'B:'";
w = gcnew ManagementEventWatcher(scope, q);
w->EventArrived += gcnew EventArrivedEventHandler(LogicalInserted);
w->Start();

実際には、すべてのバージョンでノイズが発生するわけではありません。どんなアイデアでも大歓迎です。

4

2 に答える 2

3

ここでのMicrosoftWMIサポートメッセージに基づくと、Win32_LogicalDiskでのWMIクエリが、各ポーリング間隔でフロッピーを起動せずに実行できるかどうかはわかりません。私はこの問題を自分で解決する別の方法を見つけようとしています。マネージコードで作業しているので、タイマーを実行し、DriveInfo.GetDrivesを介して使用可能なドライブを列挙することを検討しています。

更新:これをWindowsサービスで実行していて、このCodeProjectの記事で説明されている行に沿ってメッセージハンドラーを既に実装しているため(ただし、適切な例外処理とアンマネージメモリのクリーンアップを使用)、DBT_DEVICEARRIVALメッセージとDBT_DEVICEREMOVECOMPLETEメッセージのハンドラーを追加しただけです。(ここでその記事を指摘してくれたChris Dicksonのおかげです。)Win32を介してドライブ文字を取得するよりもクリーンで簡単であることがわかったため、ハンドラーでDriveInfo.GetDrivesを使用して、挿入または削除されたデバイスを判別しました。定期的なポーリングや面倒なWMIはなく、ドライブAは快適で静かな状態を保ちます。

于 2011-04-15T16:11:52.830 に答える
0

WMI から新しいアプローチを作成しました。

void MyDLPWMIDeviceListener::AddInsertUSBHandler()
{
        WqlEventQuery ^q;
        ManagementEventWatcher ^w;
        ManagementScope ^scope = gcnew ManagementScope("root\\CIMV2");
        scope->Options->EnablePrivileges = true;
        try
        {
            q = gcnew WqlEventQuery();
            q->EventClassName = "__InstanceCreationEvent";
            q->WithinInterval = TimeSpan(0, 0, 3);
        q->Condition = "TargetInstance ISA 'Win32_USBControllerDevice'";
            w = gcnew ManagementEventWatcher(scope, q);
            w->EventArrived += gcnew EventArrivedEventHandler(USBAdded);
            w->Start();
        }
        catch (Exception ^ex)
        {
            if (w != nullptr)
                w->Stop();
        }
}

その後、生成されたイベントを以下のように処理しました。

void MyDLPWMIDeviceListener::USBAdded(Object ^sender, EventArrivedEventArgs ^e)
    {   
        try {

            PropertyData ^pd = e->NewEvent->Properties["TargetInstance"];
            if (pd != nullptr)
            {
                ManagementBaseObject ^mbo = dynamic_cast<ManagementBaseObject ^>(pd->Value);
                if(mbo != nullptr && mbo->Properties["Dependent"] != nullptr
                    && mbo->Properties["Dependent"]->Value != nullptr) {
                    String ^str = (String ^)mbo->Properties["Dependent"]->Value;
                    str = str->Replace("\"","");
                    String ^splitChar = "=";
                    array<String ^> ^strArr = str->Split(splitChar->ToCharArray());

                    WqlObjectQuery ^wqlQuery = gcnew WqlObjectQuery("Select * from Win32_PnPEntity where DeviceID = '"+strArr[1]+"'");
                    ManagementObjectSearcher ^searcher = gcnew ManagementObjectSearcher(wqlQuery);
                    for each (ManagementObject ^usbCont in searcher->Get()) {
                        String ^pnpDeviceID = (String ^)usbCont->Properties["PNPDeviceID"]->Value;
                        splitChar = "\\";
                        array<String ^> ^pnpDeviceIDArr = pnpDeviceID->Split(splitChar->ToCharArray());
                        if(pnpDeviceIDArr->Length == 3) {
                            if(pnpDeviceIDArr[0] == "USB") {
                                WqlObjectQuery ^wqlQueryDisk = gcnew WqlObjectQuery("Select * from Win32_DiskDrive where PNPDeviceID LIKE '%"+pnpDeviceIDArr[2]+"%'");
                                ManagementObjectSearcher ^searcherDisk = gcnew ManagementObjectSearcher(wqlQueryDisk);
                                ManagementObjectCollection ^collectionDisk = searcherDisk->Get();
                                if(collectionDisk->Count == 0)
                                    continue;
                                else if (collectionDisk->Count == 1) {
                                    for each (ManagementObject ^disk in collectionDisk) {

                                    }
                                }
                                else {
                                    return;
                                }
                            } else {
                                return;
                            }
                        } else {
                            return;
                        }
                    }                   
                }
            }       
        } catch (Exception ^ex) {
        } 
    }
于 2011-04-17T10:01:52.340 に答える