Как получать уведомления об изменениях файлов на CD/DVD-приводе?

Я новичок в С# и должен разработать приложение Windows Form на С#. Это приложение должно отслеживать следующие вещи.

  • Контролируйте приводы CD/DVD как внешние, так и внутренние.
  • Отслеживайте файлы, которые создаются, изменяются и удаляются на CD/DVD-дисках.

Я могу получить системное уведомление о вставке CD/DVD-привода с помощью RegisterNotification и путем отслеживания WM_DEVICECHANGE сообщений в методе WndProc.

Приведенная выше реализация позволяет мне узнать, когда к ПК подключено новое устройство.

Проблема, с которой я сталкиваюсь, заключается в том, как отслеживать изменения файлов, происходящие на CD/DVD (запись/модификация). Одним из вариантов является опрос файлов на CD/DVD в качестве фонового задания. Но это будет как крайний вариант.

Я нашел IMAPIчерез который мы можем записывать на CD/DVD, но мне просто нужно следить за изменениями файлов в целях аудита.

Пожалуйста, укажите мне правильное направление, как получать изменения файлов в уведомлении CD/DVD в моей программе?

Я пробовал FileSystemWatcher, но он не работает с приводами CD/DVD.

Обновлено 7 февраля 2018 г.:

Другой подход, который я смог найти, заключался в использовании WMIqueries, которые прикреплены к WMI Events. Я нашел вопрос Best way to detect dvd insertion in drive c#, который может также держать ответ. Я хотел знать, возможно ли обнаружение модификации файловой системы DVD в WMI и могут ли какие-либо эксперты поделиться запросом на то же самое. Я надеюсь, что Аршад сможет помочь в этой области.


person Kunal Jha    schedule 01.02.2018    source источник
comment
Что вы имеете в виду под мониторингом дисков как внешних, так и внутренних?   -  person Maarten    schedule 01.02.2018
comment
Вы смотрели в wm_volumechange? Я не уверен, работает ли он с приводами DVD/CD.   -  person Sondre    schedule 01.02.2018
comment
Ваш компьютер будет иметь слабое представление о том, является ли устройство внутренним или внешним, только если оно есть или нет. Однако разве файловый наблюдатель не работает с приводами CD/DVD?   -  person BugFinder    schedule 01.02.2018
comment
@Maarten Внутренний компакт-диск и внешний (через USB-порт) DVD-приводы, о которых я говорю.   -  person Kunal Jha    schedule 01.02.2018


Ответы (1)


Подход 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

Существует пример проекта кода (VBScript), описывающий, как использовать WMI для мониторинга файловой системы. Я использовал запрос из этого примера в приведенном ниже фрагменте C#:

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.

person NGambit    schedule 08.02.2018
comment
OP может также искать, обнаруживая, что диск был вставлен. Для меня это было давно, но будет ли FSW проверять диски, в которые в настоящее время не вставлен носитель? - person Jim L; 13.02.2018
comment
@JimL OP упомянул, что он (она) может получать уведомления, когда диск вставлен. Но, как вы намекаете, вероятно, лучше использовать свойство IsReady класса DriveInfo, чтобы сначала проверить, присутствует ли диск, прежде чем использовать FileSystemWatcher. - person NGambit; 13.02.2018
comment
Обновлен ответ, чтобы сначала проверить наличие диска. - person NGambit; 13.02.2018