The best way to always detect a removable device

You should be able to use the volume id paired with total disk size and volume name to determine if a disk is the same or not, although volume id by itself should be sufficient.

The only problem might be mass produced media. In some instances the volume id, disk size and volume name would match for all copies.

EDIT I'm not sure if you can absolutely get around it for all devices generically. Hardware from each vendor is different, and the specifications are up for interpretation, which is why serial number for some devices is null, for some its not. Your only hope would be to either supply the hardware yourself or to require specific hardware which behaves in a predictable manner.

If you can write to the device, and it would be acceptable to the user, you could create a read only system hidden file containing a unique identifier (such as a guid) and use that file for comparison. This would only stop average users who run windows with the defaults (hide system files, and don't have show hidden files checked) from copying the file, and including the volume id, disk size and volume name also in your check would insist that it is only allowed to a mirrored device. It might not get all instances, but it might get enough.


USB devices are required to have a unique ID. I have used that succesfully in the past from a .NET app, and that should work equally well in a Delphi app.

You should be able to import the WMI COM objects in Delphi using the Type Library Editor, that way you can use early binding in stead of Variants.

If you need an actual sample, I'd need to lookup the C# code. Drop me a private message or email if you need it.

Just had a quick look at how you do this in .NET: you use the Management Strongly Typed Class Generator (Mgmtclassgen.exe) which is not available in the native world.

I'm not so sure about non-USB devices. You'd expect the PNP ID's to be the same for devices, but you state they are not, however I don't see the same PNP ID's with different devices in your example (if course I might overlook something obvious here ).

--jeroen

USB devices have a unique ID.

Found a few parts of the C# code that lists all USB devices:

    public static List<DiskDrive> GetUsbDiskDrives()
    {
        DiskDrive.DiskDriveCollection diskDrives = DiskDrive.GetInstances("InterfaceType = 'USB'");
        return DiskDriveList(diskDrives);
    }

    public static List<DiskDrive> DiskDriveList(DiskDrive.DiskDriveCollection diskDrives)
    {
        List<DiskDrive> result = new List<DiskDrive>();
        foreach (DiskDrive diskDrive in diskDrives)
        {
            result.Add(diskDrive);
        }
        return result;
    }

    public static string Serial(DiskDrive diskDrive)
    {
        // pick the last portion of diskDrive.PNPDeviceID:
        string[] splitted = diskDrive.PNPDeviceID.Split('\\'); // note this becomes one backslash
        string result = splitted[splitted.Length - 1];
        return result;
    }

Above pieces use the .NET System.Collections.Generic namespace so you can have a generic List.

DiskDrive is in the Win32.WMI namespace in the C# file generated by this command:

MgmtClassGen.exe Win32_DiskDrive /oWin32.WMI