【问题标题】:How to get notifications for File Changes on CD / DVD drive?如何获取 CD / DVD 驱动器上的文件更改通知?
【发布时间】:2018-07-11 15:59:28
【问题描述】:

我是 C# 新手,必须用 C# 开发一个 Windows 窗体应用程序。此应用程序应跟踪以下内容。

  • 监控外部和内部的 CD/DVD 驱动器。
  • 监控在 CD/DVD 驱动器上创建、修改和删除的文件。

我可以通过RegisterNotification 和在WndProc 方法中跟踪WM_DEVICECHANGE 消息来获得CD/DVD 驱动器插入的系统通知。

上面的实现让我知道新设备何时连接到 PC。

我面临的问题是如何跟踪 CD/DVD 上发生的文件更改(写入/修改)。一种选择是将 CD/DVD 中的文件作为后台作业进行轮询。但是,这将是最后的选择。

我找到了IMAPI,我们可以通过它写入 CD/DVD,但我只需要监控文件更改以进行审计。

请指点我如何在我的程序中接收 CD/DVD 通知上的文件更改的正确方向?

我尝试过FileSystemWatcher,但它似乎不适用于 CD/DVD 驱动器。

2018 年 2 月 7 日更新:

我能找到的另一种方法是通过附加到WMI EventsWMIqueries。我发现了一个问题Best way to detect dvd insertion in drive c#,它也可以找到答案。我想知道在 WMI 中检测 DVD 文件系统修改是否可行,以及是否有专家可以共享相同的查询。我希望Arshad 能够在这方面提供帮助。

【问题讨论】:

  • 监控外部和内部驱动器是什么意思?
  • 您查看过 wm_volumechange 吗?我不确定它是否适用于 DVD/CD 驱动器。
  • 只有当设备存在与否时,您的计算机才会知道设备是内部设备还是外部设备。但是,filewatcher 不能在 cd/dvd 驱动器上工作吗?
  • @Maarten 我所说的内部 CD 和外部(通过 USB 端口)DVD 驱动器。

标签: c# wmi wmi-query wpd


【解决方案1】:

方法一:使用FileSystemWatcher

public void ListOpticalDiscDrivesAndWatchRootDirectory()
{
    var drives = DriveInfo.GetDrives();

    foreach (var drive in drives)
    {
        if (drive.IsReady && drive.DriveType == DriveType.CDRom)
        {
            var rootDirectory = drive.RootDirectory.ToString();
            Console.WriteLine(rootDirectory);
            Watch(rootDirectory);
        }
    }
}

private void Watch(string path)
{
    var watcher = new FileSystemWatcher
    {
        Path = path,
        NotifyFilter = NotifyFilters.Attributes |
        NotifyFilters.CreationTime |
        NotifyFilters.DirectoryName |
        NotifyFilters.FileName |
        NotifyFilters.LastAccess |
        NotifyFilters.LastWrite |
        NotifyFilters.Security |
        NotifyFilters.Size,
        Filter = "*.*",
        EnableRaisingEvents = true
    };

    watcher.Changed += new FileSystemEventHandler(OnChanged);
}

private void OnChanged(object source, FileSystemEventArgs e)
{
    Console.WriteLine("Something changed!");
}

方法2:使用WMI

有一个code project sample (VBScript) 描述了如何使用 WMI 进行文件系统监控。我在下面的 C# sn-p 中使用了该示例中的查询:

using System;
using System.Management;

public class OpticalDriveWatcher
{
    private ManagementEventWatcher _wmiWatcher = new ManagementEventWatcher();

    public ManagementEventWatcher WmiWatcher
    {
        get { return _wmiWatcher; }
    }

    private void OnWmiEventReceived(object sender, EventArrivedEventArgs e)
    {
        Console.WriteLine("WMI event!");
    }

    public void WatchWithWMI(string path)
    {
        string queryString = "Select * From __InstanceOperationEvent "
                           + "WITHIN 2 "
                           + "WHERE TargetInstance ISA 'CIM_DataFile' "
                           + $"And TargetInstance.Drive='{path}'";

        WqlEventQuery wmiQuery = new WqlEventQuery(queryString);
        WmiWatcher.Query = wmiQuery;
        WmiWatcher.Start();
    }
}

问题是CIM_DataFile 仅返回本地固定磁盘上的文件实例。你可以这样称呼它

var detector = new OpticalDriveDetector();
var drive = "I:"; //You could get the optical drive you want to watch with DriveInfo as described in approach 1
detector.WatchWithWMI(drive);
detector.WmiWatcher.EventArrived += detector.OnWmiEventReceived;

当我使用 DVD-RAM 进行测试时,这两种方法对我来说都很好。

【讨论】:

  • OP 可能还在寻找是否检测到磁盘已插入。我已经有一段时间了,但是 FSW 会检查当前没有插入媒体的驱动器吗?
  • @JimL OP 提到他能够在插入磁盘时收到通知。但正如您所暗示的,在使用 FileSystemWatcher 之前,使用 DriveInfo 类的 IsReady 属性来检查磁盘是否存在可能是一个更好的主意。
  • 更新了首先检查磁盘是否存在的答案。
猜你喜欢
  • 1970-01-01
  • 2019-11-02
  • 2015-12-24
  • 2021-11-19
  • 2011-02-04
  • 2010-09-22
  • 2011-10-25
  • 2012-09-07
  • 2011-07-12
相关资源
最近更新 更多