How to get notifications for File Changes on CD / DVD drive?
Asked Answered
E

1

9

I am new to C# and have to develop a Windows Form application in C#. This application should track the following things.

  • Monitor the CD / DVD drives both external and internal.
  • Monitor the files which are created, modified and deleted on the CD/DVD drives.

I am able to get system notification for CD/DVD drive insertion by RegisterNotification and by tracking WM_DEVICECHANGE messages in the WndProc method.

The above implementation lets me know when a new device has been attached to the PC.

The problem I am facing is how track the file changes which happen on the CD/DVD (Writes / Modification). One option is to poll for the files in the CD / DVD as a background job. But, this will be as the last option.

I have found IMAPIthrough which we can write to CD/DVDs but I just need to monitor the file changes for audit purposes.

Kindly point me to right direction on how to receive file changes on the CD/DVD notification in my program ?

I have tried FileSystemWatcher but it doesn't seem to work with CD/DVD drives.

Updated on 07-Feb-2018:

The another approach I could find was via WMIqueries which are attached to WMI Events. I have found a question Best way to detect dvd insertion in drive c# which could also hold the answer. I wanted to know if the detection of DVD file system modification is feasible in WMI and if any experts can share the query for the same. I hope if Arshad would be able to help in this area.

Evasive answered 1/2, 2018 at 10:45 Comment(4)
What do you mean with monitoring the Drives both external and internal?Assignor
Have you looked into wm_volumechange? Im not sure if it works with DVD/CD drives.Unfledged
Your computer will have little idea if a device is internal or external only if its there or not.. however, doesnt filewatcher work on cd/dvd drives?Satirical
@Assignor The internal CD and external (via USB port) DVD drives I am talking about.Evasive
M
8

Approach 1 : Using 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!");
}

Approach 2 : Using WMI

There's a code project sample (VBScript) describing how to use WMI for file system monitoring. I used the query from that sample in the C# snippet below :

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();
    }
}

The catch is that CIM_DataFile returns only instances of files on local fixed disks. You can call this as follows

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;

Both approaches worked fine for me when I tested with a DVD-RAM.

Mazurka answered 8/2, 2018 at 20:4 Comment(3)
OP may be looking for also detecting that a disk was inserted. It's been a while for me, but will FSW check drives that don't currently have media inserted?Harvard
@JimL OP mentioned that (s)he is able to get notifications when a disk is inserted. But as you’re alluding, it’s probably a better idea to use IsReady property of DriveInfo class to check if a disk is present first before using FileSystemWatcher.Mazurka
Updated the answer to first check if a disk is present.Mazurka

© 2022 - 2024 — McMap. All rights reserved.