Floppy noise in C# WMI - Win32_LogicalDisk Class
I am trying to track USB device insertions and CD/DVD insertions on Windows by using WMI. However when I use Win32_LogicalDisk class to track those events, floppy starts to make noise.
My queries are like below. First one is for USB and second one is for CD.
q = gcnew WqlEventQuery();
q->EventClassName = "__InstanceCreationEvent";
q->WithinInterval = TimeSpan(0, 0, 3);
q->Condition = "T开发者_StackOverflow社区argetInstance 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();
Actually it does not make noise on all versions. Any idea will be greatly appreciated.
Based on a Microsoft WMI support message here, I'm not certain a WMI query on Win32_LogicalDisk is going to be able to run without firing up the floppies on each polling interval. I'm trying to find an alternate way of solving this issue myself; as I'm working in managed code, I'm considering just running a timer and enumerating the available drives via DriveInfo.GetDrives.
Update: As I was doing this in a Windows service and already had implemented a message handler along the lines described in this CodeProject article (but with proper exception handling and unmanaged memory cleanup), I simply added handlers for the DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE messages. (Due credit to Chris Dickson for pointing that article out to me here.) I used DriveInfo.GetDrives in the handler to determine which devices had been inserted or removed, as I found that cleaner and simpler than getting at the drive letter via Win32. There's no periodic polling involved, no messy WMI, and drive A now stays nice and quiet.
I have created a new approach from 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();
}
}
After that I have handled the generated event like below:
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) {
}
}
精彩评论