如何使用 C# 获取连接到 PC 的 SD 卡的驱动器号

How to get the drive letter of an SD Card connected to a PC, using C#

如何从 C# .NET Framework 应用程序获取连接到 PC 的 SD 卡的驱动器号?

我查看了有关此主题的建议问题,包括 this, & ,但其中 none 为我提供了我需要的解决方案。

使用 System.IO.DriveInfo.GetDrives() 或 System.Management.ManagementObjectSearcher() 查询“Win32_LogicalDisk”,我可以得到所有设备的驱动器盘符,但我不知道是哪个设备( s) 是 SD 卡。 将 System.Management.ManagementObjectSearcher() 与查询“CIM_LogicalDevice”、“Caption = 'SDHC Card'”一起使用,我得到了 2 个带有“SDHC 卡”标题 属性 但没有驱动器盘符的设备。

如何获取SD卡或卡reader的盘符?

这是我到目前为止尝试过的方法:

using System;
using System.Management;

namespace Code3
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("\tfrom: 'ManagementObjectSearcher()' with query \"Win32_LogicalDisk\"");
            var searcher1 = new ManagementObjectSearcher(@"\root\cimv2", "SELECT * FROM Win32_LogicalDisk");
            foreach (ManagementBaseObject disk in searcher1.Get())
            {
                string diskID = disk.GetPropertyValue("DeviceID").ToString();
                int driveType = Convert.ToInt32(disk.GetPropertyValue("DriveType"));
                string diskCaption = disk.GetPropertyValue("Caption").ToString();
                string diskDescription = disk.GetPropertyValue("Description").ToString();
                string diskName = disk.GetPropertyValue("Name").ToString();
                int diskMediaType = Convert.ToInt32(disk.GetPropertyValue("MediaType"));
                Console.WriteLine($"{diskName} - ID: {diskID},  Caption: {diskCaption},  Desc.: {diskDescription,-16},  Drive Type: {driveType},  Media Type: {diskMediaType}.");
            }
            Console.WriteLine();

            Console.WriteLine("\tfrom: 'ManagementObjectSearcher()' with query SelectQuery(\"CIM_LogicalDevice\", \"Caption = 'SDHC Card'\")");
            ManagementScope mgmtScope = new ManagementScope(@"\root\cimv2");
            SelectQuery devQuery = new SelectQuery("CIM_LogicalDevice", "Caption = 'SDHC Card'");
            var searcher2 = new ManagementObjectSearcher(mgmtScope, devQuery);

            foreach (ManagementBaseObject device in searcher2.Get())
            {
                Console.WriteLine($"{device.GetPropertyValue("Name"),-15} - Caption: {device.GetPropertyValue("Caption")},  Device ID: {device.GetPropertyValue("DeviceID")}.");
                continue; // ... to skip property display

                if (!string.IsNullOrEmpty(device.GetPropertyValue("Name").ToString()))
                {
                    PropertyDataCollection props = device.Properties;
                    Console.WriteLine($"\n\t\tProperties of {device.GetPropertyValue("DeviceID")} Drive: \n");
                    foreach (var prop in device.Properties)
                    {
                        if (prop.Value != null)
                            Console.WriteLine($"{prop.Name,-20} - {prop.Type,-8} - {prop.Value ?? "(null)"}");
                    }
                    Console.WriteLine();
                }
            }

            Console.ReadKey();
        }
    }
}

谢谢你能给我的任何帮助。

编辑: 从“CIM_LogicalDisk”,我可以看到“F:”驱动器是我的 SD-Card。 (来自 'VolumeName' 属性。)

从“CIM_LogicalDevice”,我可以看到“\.\PHYSICALDRIVE1”和“PCISTOR\DISK&VEN_RSPER&PROD_RTS5208LUN0&REV_1。 00[=41=]00”是我的 SD-Card。 (来自 'Name'、'Caption'、and/or 'Model' 属性。)

但是我的应用程序看不到这个!请注意,'drive letter' 和 'PHYSICALDRIVE number' 不会保持相关性,并且会随着插入和移除不同的可移动设备而改变。

如何获取我的代码以在逻辑驱动器和物理驱动器之间建立连接?

如果你确定你的SD卡的卷标总是“SDHC卡”(我不是),那么你可以使用以下方法:

DriveInfo class contains a static method GetDrives which returns an array of DriveInfo instances. Each instance itself represents on logical drive. You can use the VolumeLabel属性检查卷名。

所以像...

var drives = DriveInfo.GetDrives().Where(drive => drive.VolumeLabel == "SDHC Card");

...returns 卷名为“SDHC 卡”的所有驱动器。 如果要获取逻辑驱动器的盘符,可以使用具体实例的 RootDirectory 属性 访问它。

喜欢:

var drives = DriveInfo.GetDrives().Where(drive => drive.VolumeLabel == "SDHC Card");

foreach (var drive in drives)
    Console.WriteLine(drive.RootDirectory.FullName);

我终于找到了解决方案。使用 WMI 关联 classes,我能够在逻辑驱动器和物理驱动器之间建立连接。

这个class是我的解决方案:

using System.Collections.Generic;
using System.Management;

namespace GetSDCard
{
    public class GetSDCards
    {
        public Card[] GetCards()
        {
            return FindCards().ToArray();
        }

        private List<Card> FindCards()
        {
            List<Card> cards = new List<Card>();

            //  Get Disk Drives collection (Win32_DiskDrive)
            string queryDD = "SELECT * FROM Win32_DiskDrive WHERE Caption = 'SDHC Card'";
            using (ManagementObjectSearcher searchDD = new ManagementObjectSearcher(queryDD))
            {
                ManagementObjectCollection colDiskDrives = searchDD.Get();
                foreach (ManagementBaseObject objDrive in colDiskDrives)
                {
                    //  Get associated Partitions collection (Win32_DiskDriveToDiskPartition)
                    string queryPart = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{objDrive["DeviceID"]}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition";
                    using (ManagementObjectSearcher searchPart = new ManagementObjectSearcher(queryPart))
                    {
                        ManagementObjectCollection colPartitions = searchPart.Get();
                        foreach (ManagementBaseObject objPartition in colPartitions)
                        {
                            //  Get associated Logical Disk collection (Win32_LogicalDiskToPartition)
                            string queryLD = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{objPartition["DeviceID"]}'}} WHERE AssocClass = Win32_LogicalDiskToPartition";
                            using (ManagementObjectSearcher searchLD = new ManagementObjectSearcher(queryLD))
                            {
                                ManagementObjectCollection colLogicalDisks = searchLD.Get();
                                foreach (ManagementBaseObject objLogicalDisk in colLogicalDisks)
                                    cards.Add(new Card($"{objLogicalDisk["DeviceID"]}", $"{objDrive["Caption"]}", $"{objLogicalDisk["VolumeName"]}"));
                            }
                        }
                    }
                }
            }

            return cards;
        }


        public class Card
        {
            public string Drive { get; set; }
            public string Name { get; set; }
            public string Label { get; set; }

            public Card(string _drive, string _name, string _label)
            {
                Drive = _drive;
                Name = _name;
                Label = _label;
            }
        }
    }
}

这是一个简单的控制台应用程序,用于演示如何使用它。

using GetSDCard;
using System;
using System.IO;

namespace FindSDCard_Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            GetSDCards getter = new GetSDCards();
            GetSDCards.Card[] sdCards = getter.GetCards();
            if (sdCards.Length == 0)
                Console.WriteLine("No SD Cards found.");
            else
            {
                string sdDrive = sdCards[0].Drive;
                Console.WriteLine($"Root folder of SD Card '{sdDrive}':");
                foreach (var folder in Directory.GetDirectories(sdDrive))
                    Console.WriteLine($"\t{folder}");
            }
        }
    }
}

我希望这可以为您节省我经历的挫败感。