【问题标题】:Best way to detect dvd insertion in drive c#检测驱动器 c# 中 dvd 插入的最佳方法
【发布时间】:2023-03-13 09:28:01
【问题描述】:

我尝试使用 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。因此,当插入磁盘时,准备好的磁盘将首先在组合框中列出,用户可以轻松弹出驱动器。

【问题讨论】:

  • 你在检查基于 Windows 的机器吗?
  • 是的,我的电脑有 Windows 8,但其他电脑有 Windows 7 和 5 有 1 次它抛出错误告诉我插入磁盘。
  • 你用我的回答试过了吗
  • 按照您的建议验证 WMI 存储库。完成后更新问题。

标签: c# wmi driveinfo


【解决方案1】:

你可以试试这些代码:

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 类。 This 会帮助你。

【讨论】:

  • 重置 WMI 有效。但我认为管理解决方案将证明比使用 WMI 更好。
【解决方案2】:

参考以下代码:

foreach (DriveInfo drive in DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.CDRom))  
    MessageBox.Show(drive.Name + " " + drive.IsReady.ToString());  

参考链接:

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/1ecb74cd-d193-40f5-9aa3-47a3c9adb4ea/

堆栈链接:

Detecting if disc is in DVD drive

【讨论】:

    【解决方案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);
    }
    

    【讨论】:

    • 您的代码似乎没有按照所写的方式执行。没有名为“DriveSystemWatcher”的类。
    • 调用 OpticalDiskArrived Handler 大约需要 10-12 秒。还有其他人遇到过类似问题吗?
    • 我在我的应用程序中使用了这个代码。见rbsoft.org/downloads/easy-disk-catalog-maker
    • 您还可以使用 DriveWatcher 类的 Interval 参数调整轮询间隔。
    猜你喜欢
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多