С#, как узнать, является ли съемный диск USB-накопителем или SD-картой?

Платформа Windows 7, С#

Я использую следующий оператор для перечисления всех дисков:

DriveInfo[] drives = DriveInfo.GetDrives();

затем я могу использовать DriveType, чтобы узнать все эти съемные диски:

foreach (var drive in drives)
{
     if(drive.DriveType == DriveType.Removable)
         yield return drive;
}

теперь моя проблема в том, что диск SD-карты и USB-флеш-диск используют один и тот же привод. Тип: съемный, так как я могу найти только USB-флеш-диск?

Спасибо!


person Oh My Dog    schedule 22.07.2015    source источник


Ответы (2)


Вы можете воспользоваться ManagementObjectSearcher, используя его для запроса дисководов USB, затем получить соответствующую букву устройства и вернуть только DriveInfo, из которых RootDirectory.Name содержится в наборе результатов.

Использование выражений запросов LINQ:

static IEnumerable<DriveInfo> GetUsbDevices()
{
    IEnumerable<string> usbDrivesLetters = from drive in new ManagementObjectSearcher("select * from Win32_DiskDrive WHERE InterfaceType='USB'").Get().Cast<ManagementObject>()
                                           from o in drive.GetRelated("Win32_DiskPartition").Cast<ManagementObject>()
                                           from i in o.GetRelated("Win32_LogicalDisk").Cast<ManagementObject>()
                                           select string.Format("{0}\\", i["Name"]);

    return from drive in DriveInfo.GetDrives()
           where drive.DriveType == DriveType.Removable && usbDrivesLetters.Contains(drive.RootDirectory.Name)
           select drive;
}

Использование методов расширения LINQ:

static IEnumerable<DriveInfo> GetUsbDevices()
{
    IEnumerable<string> usbDrivesLetters = new ManagementObjectSearcher("select * from Win32_DiskDrive WHERE InterfaceType='USB'").Get().Cast<ManagementObject>()
        .SelectMany(drive => drive.GetRelated("Win32_DiskPartition").Cast<ManagementObject>())
        .SelectMany(o => o.GetRelated("Win32_LogicalDisk").Cast<ManagementObject>())
        .Select(i => Convert.ToString(i["Name"]) + "\\");

    return DriveInfo.GetDrives().Where(drive => drive.DriveType == DriveType.Removable && usbDrivesLetters.Contains(drive.RootDirectory.Name));
}

Использование foreach:

static IEnumerable<string> GetUsbDrivesLetters()
{                
    foreach (ManagementObject drive in new ManagementObjectSearcher("select * from Win32_DiskDrive WHERE InterfaceType='USB'").Get())
        foreach (ManagementObject o in drive.GetRelated("Win32_DiskPartition"))
            foreach (ManagementObject i in o.GetRelated("Win32_LogicalDisk"))
                yield return string.Format("{0}\\", i["Name"]);
}

static IEnumerable<DriveInfo> GetUsbDevices()
{
    IEnumerable<string> usbDrivesLetters = GetUsbDrivesLetters();
    foreach (DriveInfo drive in DriveInfo.GetDrives())
        if (drive.DriveType == DriveType.Removable && usbDrivesLetters.Contains(drive.RootDirectory.Name))
            yield return drive;
}

Чтобы использовать ManagementObject, вам нужно добавить ссылку на System.Management

Я не проверял это хорошо, потому что сейчас у меня нет SD-карты, но я надеюсь, что это поможет

person Matteo Umili    schedule 22.07.2015
comment
привет @codroipo, usbDrivesLetters возвращает все съемные диски, включая SD-карту. Но мне нравится ManagementObjectSearcher, он выглядит гораздо более профессионально, лол, поэтому не могли бы вы немного помочь, как отфильтровать только USB-накопитель? - person Oh My Dog; 23.07.2015
comment
@OhMyDog В диспетчере устройств в каком узле отображается ваше устройство чтения SD-карт? - person Matteo Umili; 23.07.2015
comment
@OhMyDog Можете ли вы также сказать мне, что выводит new ManagementObjectSearcher("select * from Win32_DiskDrive WHERE InterfaceType='USB'").Get().Cast<ManagementObject>().Select(f => (string)f["PNPDeviceID"]).ToList()? - person Matteo Umili; 23.07.2015
comment
задача решена. Я проверил pnpDeviceID и нашел разницу между USB-flash и SD-картой, спасибо codroipo! - person Oh My Dog; 24.07.2015
comment
Не могли бы вы отредактировать свой ответ, чтобы он был правильным, после того, как вы знаете, как это сделать сейчас? Спасибо - person Tom Doodler; 14.09.2016
comment
В Windows 10 Win32_DiskDrive InterfaceType='USB' не возвращает все USB-накопители (они возвращают InterfaceType='SCSI'). Я думаю, что это связано с USB-накопителями типа C. )-: - person tamshi; 26.09.2018

Мне пришлось проверить наличие USB-устройств в старом проекте, и я решил это следующим образом:

 Win32.DEV_BROADCAST_DEVICEINTERFACE deviceInterface;
 deviceInterface = (Win32.DEV_BROADCAST_DEVICEINTERFACE)
 string name = new string(deviceInterface.dbcc_name);
 Guid g = new Guid(deviceInterface.dbcc_classguid);
 if (g.ToString() == "a5dcbf10-6530-11d2-901f-00c04fb951ed")
 {*DO SOMETHING*}

Я получаю GUID и проверяю, является ли GUID устройства USB-GUID.

person npit    schedule 22.07.2015
comment
Я не совсем уверен, но я думаю, что у OP нет GUID - person DanielV; 22.07.2015
comment
также спасибо, npit, но я сосредоточился на ответе codroipo, извините, что не попробовал ваш. - person Oh My Dog; 24.07.2015