While writing a small program that monitors the connection / disconnection of USB drives for the current time, there was a problem when updating the list of connected devices: when the program starts, the function works well, but if I start it from the redefined WndProc method at the time of activation / deactivation events, The program falls out in the Disconnected context. I approximately understand the essence of the problem, but have not yet been able to solve it. I started the function in a separate thread, but in this case I cannot update the form data.
Event handling:
protected override void WndProc(ref Message msg) { base.WndProc(ref msg); if ((msg.Msg != WM_DEVICECHANGE) || (msg.LParam == IntPtr.Zero)) return; int eventType = msg.WParam.ToInt32(); DEV_BROADCAST_VOLUME volume = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(msg.LParam, typeof(DEV_BROADCAST_VOLUME)); DEV_BROADCAST_DEVICEINTERFACE dvi = (DEV_BROADCAST_DEVICEINTERFACE)Marshal.PtrToStructure(msg.LParam, typeof(DEV_BROADCAST_DEVICEINTERFACE)); if (volume.dbcv_devicetype == DBT_DEVTYP_VOLUME) //DBT_DEVTYP_VOLUME { switch (msg.WParam.ToInt32()) { // New device inserted... case DBT_DEVICEARRIVAL: //MessageBox.Show(string.Format("A storage device has been inserted; Drive :{0} - {1}", DeviceName, ToDriveName(volume.dbcv_unitmask)), "Detect USB"); break; // Device Removed. case DBT_DEVICEREMOVECOMPLETE: //MessageBox.Show("Storage has been removed.", "Detect USB"); break; } Thread thread = new Thread(this.UpdateDeviceList); thread.Start(); } } Update function:
private void UpdateDeviceList() { if (this.uinf == null) return; if (this.usbList != null) this.usbList.Clear(); this.usbList = uinf.GetUSBFlashDrive(); this.bs.ResetBindings(false); } UPD1 Class with GetUSBFlashDrive () function:
class UsbDeviceInfo { string _serialNumber; string _driveLetter; public string getSerialNumberFromDriveLetter(string driveLetter) { this._driveLetter = driveLetter.ToUpper(); if(!this._driveLetter.Contains(":")) { this._driveLetter += ":"; } matchDriveLetterWithSerial(); return this._serialNumber; } private void matchDriveLetterWithSerial() { string[] diskArray; string driveNumber; string driveLetter; ManagementObjectSearcher searcher1 = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDiskToPartition"); foreach (ManagementObject dm in searcher1.Get()) { diskArray = null; driveLetter = getValueInQuotes(dm["Dependent"].ToString()); diskArray = getValueInQuotes(dm["Antecedent"].ToString()).Split(','); driveNumber = diskArray[0].Remove(0, 6).Trim(); if(driveLetter==this._driveLetter){ /* This is where we get the drive serial */ ManagementObjectSearcher disks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive"); foreach (ManagementObject disk in disks.Get()) { if (disk["Name"].ToString() == ("\\\\.\\PHYSICALDRIVE" + driveNumber) & disk["InterfaceType"].ToString() == "USB") { this._serialNumber = parseSerialFromDeviceID(disk["PNPDeviceID"].ToString()); } } } } } private string parseSerialFromDeviceID(string deviceId) { string[] splitDeviceId = deviceId.Split('\\'); string[] serialArray; string serial; int arrayLen = splitDeviceId.Length-1; serialArray = splitDeviceId[arrayLen].Split('&'); serial = serialArray[0]; return serial; } private string getValueInQuotes(string inValue) { string parsedValue = ""; int posFoundStart = 0; int posFoundEnd = 0; posFoundStart = inValue.IndexOf("\""); posFoundEnd = inValue.IndexOf("\"", posFoundStart + 1); parsedValue = inValue.Substring(posFoundStart + 1, (posFoundEnd - posFoundStart) - 1); return parsedValue; } public string GetCPUId() { string cpuInfo = String.Empty; string temp = String.Empty; ManagementClass mc = new ManagementClass("Win32_Processor"); ManagementObjectCollection moc = mc.GetInstances(); foreach(ManagementObject mo in moc) { if(cpuInfo==String.Empty) { cpuInfo = mo.Properties["ProcessorId"].Value.ToString(); } } return cpuInfo; } public List<string> GetUSBFlashDrive() { List<string> ret = new List<string>(); foreach (ManagementObject drive in new ManagementObjectSearcher("select * from Win32_DiskDrive where InterfaceType='USB'").Get()) { foreach (ManagementObject partition in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + drive["DeviceID"] + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get()) { foreach (ManagementObject disk in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition["DeviceID"] + "'} WHERE AssocClass = Win32_LogicalDiskToPartition").Get()) { ret.Add(String.Format(new FileSizeFormatProvider(), "{1} {2}, {0:fs} ({3})", disk["Size"], disk["Description"].ToString(), disk["Name"].ToString(), this.getSerialNumberFromDriveLetter(disk["Name"].ToString()))); } } } return ret; } } Descriptions of the action:
Context 0x1e799e88 is disabled. No proxy will be used to service the request to this COM component. This may result in damage or loss of data. To eliminate this problem, make sure that all contexts / apartments still exist before the application completes its use of RuntimeCallableWrappers representing the COM components in them.
Here on this line is painted:
foreach (ManagementObject drive in new ManagementObjectSearcher("select * from Win32_DiskDrive where InterfaceType='USB'").Get()) UPD2 Thank you all for the "help", I solved the problem myself. Carried method in backgroundWorker:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { Debug.WriteLine("UpdateDeviceList. ThreadId: " + Thread.CurrentThread.ManagedThreadId); UsbDeviceInfo uinf = new UsbDeviceInfo(); e.Result = uinf.GetUSBFlashDrive(); } private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Result != null) { List<string> usbList = (List<string>)e.Result; this.lbDeviceList.DataSource = usbList; Debug.WriteLine("UpdateDeviceList completed! ThreadId: " + Thread.CurrentThread.ManagedThreadId); } }