Лучший способ обнаружить вставку DVD в диск C#
Я попытался использовать WMI для обнаружения вставки нового носителя в дисковод, используя следующий код. Но есть ли управляемое решение, такое как использование цикла в фоновом потоке с DriveInfo.GetDrives? Какой лучший способ сделать это? Я получаю диалоговое окно "Диск не в дисководе, пожалуйста, вставьте диск" с кнопкой "Отмена", "Повторить" и "Продолжить" на другом компьютере, когда я попробовал следующий код? На майской машине все отлично работает.
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;
}
}
В основном то, что я делаю, это событие загрузки формы, которое называется Drive Watcher. Поэтому, когда диск вставлен, готовый диск будет указан первым в поле со списком, и пользователь сможет легко извлечь диск.
3 ответа
Я иду со следующим решением. Это 100% управляемое решение. Он не использует WMI и отлично работает.
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;
}
Вы можете использовать это следующим образом.
var driveWatcher = new DriveWatcher();
driveWatcher.OpticalDiskArrived += DriveWatcherOnOpticalDiskArrived;
driveWatcher.Start();
private void DriveWatcherOnOpticalDiskArrived(object sender, OpticalDiskArrivedEventArgs e)
{
MessageBox.Show(e.Drive.Name);
}
Вы можете попробовать с этим кодом:
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");
}
если он работает на вашем компьютере и не работает ни на одном другом оконном компьютере, вам придется перестроить / восстановить / перерегистрировать классы WMI этого компьютера. Это поможет вам в этом.
См. Следующий код:
foreach (DriveInfo drive in DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.CDRom))
MessageBox.Show(drive.Name + " " + drive.IsReady.ToString());
Ссылка Ссылка:
Ссылка на стек: