I tried using WMI to detect new media insertion in Disk Drive using following code. But is there managed solution like using loop in background thread with DriveInfo.GetDrives? Which is best way to do this? I'm getting 'Disk is not in the drive please insert disk' dialog with abort, retry and continue button on other pc when i tried the following code? On may machine it works fine.
private void DriveWatcher()
{
try
{
var wqlEventQuery = new WqlEventQuery
{
EventClassName = "__InstanceModificationEvent",
WithinInterval = new TimeSpan(0, 0, 1),
Condition =
@"TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5"
};
var connectionOptions = new ConnectionOptions
{
EnablePrivileges = true,
Authority = null,
Authentication = AuthenticationLevel.Default
};
var managementScope = new ManagementScope("\\root\\CIMV2", connectionOptions);
ManagementEventWatcher = new ManagementEventWatcher(managementScope, wqlEventQuery);
ManagementEventWatcher.EventArrived += CdrEventArrived;
ManagementEventWatcher.Start();
}
catch (ManagementException e)
{
MessageBox.Show(e.Message, e.GetType().ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CdrEventArrived(object sender, EventArrivedEventArgs e)
{
var wmiDevice = (ManagementBaseObject) e.NewEvent["TargetInstance"];
if (wmiDevice.Properties["VolumeName"].Value != null)
GetDrives();
else
GetDrives();
}
private void GetDrives()
{
if (InvokeRequired)
{
Invoke(new GetDrivesDelegate(GetDrives));
}
else
{
toolStripComboBoxDrives.Items.Clear();
DriveInfo[] drives = DriveInfo.GetDrives();
_drives = new Dictionary<string, DriveInfo>();
int selectedIndex = 0;
foreach (DriveInfo drive in drives)
{
if (drive.DriveType.Equals(DriveType.CDRom))
{
if (drive.IsReady)
{
string name = string.Format("{0} ({1})", drive.VolumeLabel, drive.Name.Substring(0, 2));
int selectedDrive = toolStripComboBoxDrives.Items.Add(name);
_drives.Add(name, drive);
selectedIndex = selectedDrive;
}
else
{
toolStripComboBoxDrives.Items.Add(drive.Name);
_drives.Add(drive.Name, drive);
}
}
}
toolStripComboBoxDrives.SelectedIndex = selectedIndex;
}
}
Basically what i'm doing is on form load event called Drive Watcher. So when disk is inserted ready disk will be listed first in combo box and user can eject the drive easily.
you can try with these code :
public void networkDevice()
{
try
{
WqlEventQuery q = new WqlEventQuery();
q.EventClassName = "__InstanceModificationEvent";
q.WithinInterval = new TimeSpan(0, 0, 1);
q.Condition = @"TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5";
ConnectionOptions opt = new ConnectionOptions();
opt.EnablePrivileges = true;
opt.Authority = null;
opt.Authentication = AuthenticationLevel.Default;
//opt.Username = "Administrator";
//opt.Password = "";
ManagementScope scope = new ManagementScope("\\root\\CIMV2", opt);
ManagementEventWatcher watcher = new ManagementEventWatcher(scope, q);
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Start();
}
catch (ManagementException e)
{
Console.WriteLine(e.Message);
}
}
void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject wmiDevice = (ManagementBaseObject)e.NewEvent["TargetInstance"];
string driveName = (string)wmiDevice["DeviceID"];
Console.WriteLine(driveName);
Console.WriteLine(wmiDevice.Properties["VolumeName"].Value);
Console.WriteLine((string)wmiDevice["Name"]);
if (wmiDevice.Properties["VolumeName"].Value != null)
Console.WriteLine("CD has been inserted");
else
Console.WriteLine("CD has been ejected");
}
if it works on your machine and does not work on any other window based machine, then you have to rebuild/repair/re-register that machine's WMI classes. This will help you in that.
Refer Following Code:
foreach (DriveInfo drive in DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.CDRom))
MessageBox.Show(drive.Name + " " + drive.IsReady.ToString());
Referance Link:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/1ecb74cd-d193-40f5-9aa3-47a3c9adb4ea/
Stack Link:
Detecting if disc is in DVD drive
I'm going with following solution. It's 100% managed solution. It's not using WMI and works great.
internal class DriveWatcher
{
public delegate void OpticalDiskArrivedEventHandler(Object sender, OpticalDiskArrivedEventArgs e);
/// <summary>
/// Gets or sets the time, in seconds, before the drive watcher checks for new media insertion relative to the last occurance of check.
/// </summary>
public int Interval = 1;
private Timer _driveTimer;
private Dictionary<string, bool> _drives;
private bool _haveDisk;
/// <summary>
/// Occurs when a new optical disk is inserted or ejected.
/// </summary>
public event OpticalDiskArrivedEventHandler OpticalDiskArrived;
private void OnOpticalDiskArrived(OpticalDiskArrivedEventArgs e)
{
OpticalDiskArrivedEventHandler handler = OpticalDiskArrived;
if (handler != null) handler(this, e);
}
public void Start()
{
_drives = new Dictionary<string, bool>();
foreach (
DriveInfo drive in
DriveInfo.GetDrives().Where(driveInfo => driveInfo.DriveType.Equals(DriveType.CDRom)))
{
_drives.Add(drive.Name, drive.IsReady);
}
_driveTimer = new Timer {Interval = Interval*1000};
_driveTimer.Elapsed += DriveTimerOnElapsed;
_driveTimer.Start();
}
public void Stop()
{
if (_driveTimer != null)
{
_driveTimer.Stop();
_driveTimer.Dispose();
}
}
private void DriveTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
{
if (!_haveDisk)
{
try
{
_haveDisk = true;
foreach (DriveInfo drive in from drive in DriveInfo.GetDrives()
where drive.DriveType.Equals(DriveType.CDRom)
where _drives.ContainsKey(drive.Name)
where !_drives[drive.Name].Equals(drive.IsReady)
select drive)
{
_drives[drive.Name] = drive.IsReady;
OnOpticalDiskArrived(new OpticalDiskArrivedEventArgs {Drive = drive});
}
}
catch (Exception exception)
{
Debug.Write(exception.Message);
}
finally
{
_haveDisk = false;
}
}
}
}
internal class OpticalDiskArrivedEventArgs : EventArgs
{
public DriveInfo Drive;
}
You can use this as follows.
var driveWatcher = new DriveWatcher();
driveWatcher.OpticalDiskArrived += DriveWatcherOnOpticalDiskArrived;
driveWatcher.Start();
private void DriveWatcherOnOpticalDiskArrived(object sender, OpticalDiskArrivedEventArgs e)
{
MessageBox.Show(e.Drive.Name);
}