获取引导驱动器的序列号和其他信息

8
我试图获取启动驱动器的序列号,但我还没有弄清如何做到这一点。
我知道分区不等于硬盘,但我想要启动分区的序列号。
目前我有以下内容:
        var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");

        int i = 0;
        foreach (ManagementObject wmi_HD in searcher.Get())
        {
            // get the hardware serial no.
            if (wmi_HD["SerialNumber"] == null)
                richTextBox1.Text += "None" + Environment.NewLine;
            else
                richTextBox1.Text += "Name: " + wmi_HD["Name"] + Environment.NewLine;
                richTextBox1.Text += "SerialNumber: " + wmi_HD["SerialNumber"] + Environment.NewLine;
                richTextBox1.Text += "MediaType: " + wmi_HD["MediaType"] + Environment.NewLine;
                richTextBox1.Text += "Removable: " + wmi_HD["Removable"] + Environment.NewLine;

            ++i;
        }

我已经在这里查找:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa394346(v=vs.85).aspx#properties

想要看看是否是启动驱动器,但什么都没发现。

除了SerialNumber以外,其他的信息都是空白的。

这是以上代码返回的内容:

Name:

SerialNumber: 5YZ01J34

MediaType:

Removable:

如何获取启动驱动器的序列号以及上述未显示的信息?

再次感谢!


在我的系统上(它只有一个内部SATA硬盘),除了“SerialNumber”和“Tag”之外,所有值都为NULL;“Tag”是“\.\PHYSICALDRIVE0”。在“Win32_PhysicalMedia”中没有任何信息告诉您它是否是引导磁盘。(无论如何,您不会从物理介质启动;您会从逻辑磁盘启动,该磁盘位于“Win32_LogicalDisk”中,但它仅列出分区;它不会告诉您哪个分区是从中启动的。您可能需要获取免费的MagWMI组件-包含的演示版可让您执行WMI查询并查看输出。 - Ken White
谢谢您的建议,但我尽量避免使用任何第三方应用程序。如果我遇到问题,那么我就会受制于它们。到目前为止,我已经成功避免了这种情况。 - ErocM
我建议使用MagWMI演示来让看看各种查询结果中可用的内容,而不是用于其他任何目的。这是一个非常有用(免费)的实用程序,用于测试WMI相关内容并查看所有可用的输出。 - Ken White
啊,抱歉我看错了。谢谢,我会去检查一下的。 - ErocM
你是否意识到这是一种非常糟糕的识别计算机的方式?在RAID设置中,某些控制器会给出任何可用驱动器的ID。 - Loren Pechtel
1个回答

11
这里讨论的是一个可启动的驱动器,而不是磁盘。驱动器是逻辑上的,由一个字母表示(C、D等),而磁盘是物理上的,由一个数字表示(从0到N)。在您的示例中,您使用了WMI和Win32_PhysicalMedia,这是错误的,因为这个类是关于磁盘而不是驱动器的。
以下是使用P/Invoke实现的方法:
namespace ConsoleApplication3
{
    using System.Runtime.InteropServices;
    using System.Text;

    public class Drive
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool GetVolumeInformation(
            string rootPathName,
            StringBuilder volumeNameBuffer,
            int volumeNameSize,
            ref uint volumeSerialNumber,
            ref uint maximumComponentLength,
            ref uint fileSystemFlags,
            StringBuilder fileSystemNameBuffer,
            int nFileSystemNameSize);

        public string VolumeName { get; private set; }

        public string FileSystemName { get; private set; }

        public uint SerialNumber { get; private set; }

        public string DriveLetter { get; private set; }

        public static Drive GetDrive(string driveLetter)
        {
            const int VolumeNameSize = 255;
            const int FileSystemNameBufferSize = 255;
            StringBuilder volumeNameBuffer = new StringBuilder(VolumeNameSize);
            uint volumeSerialNumber = 0;
            uint maximumComponentLength = 0;
            uint fileSystemFeatures = 0;
            StringBuilder fileSystemNameBuffer = new StringBuilder(FileSystemNameBufferSize);

            if (GetVolumeInformation(
                string.Format("{0}:\\", driveLetter),
                volumeNameBuffer,
                VolumeNameSize,
                ref volumeSerialNumber,
                ref maximumComponentLength,
                ref fileSystemFeatures,
                fileSystemNameBuffer,
                FileSystemNameBufferSize))
            {
                return new Drive
                    {
                        DriveLetter = driveLetter,
                        FileSystemName = fileSystemNameBuffer.ToString(),
                        VolumeName = volumeNameBuffer.ToString(),
                        SerialNumber = volumeSerialNumber
                    };
            }

            // Something failed, returns null
            return null;
        }
    }
}


Drive drive = Drive.GetDrive("C");

Console.WriteLine(string.Format("Volumne name: {0}", drive.VolumeName));
Console.WriteLine(string.Format("File system name: {0}", drive.FileSystemName));
Console.WriteLine(string.Format("SerialNumber: {0:X}", drive.SerialNumber));

现在,使用WMI实现相同的功能:
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk");

foreach (ManagementObject drive in searcher.Get())
{
    Console.WriteLine("-------");
    Console.WriteLine(string.Format("VolumeName: {0}", drive["VolumeName"]));
    Console.WriteLine(string.Format("VolumeSerialNumber: {0}", drive["VolumeSerialNumber"]));
    Console.WriteLine(string.Format("MediaType: {0}", drive["MediaType"]));
    Console.WriteLine(string.Format("FileSystem: {0}", drive["FileSystem"]));
}

请注意,我使用了 Win32_LogicalDisk,因为我们正在谈论驱动器(此处称为逻辑磁盘)。

Windows 可能会将“驱动器”这个术语专门用作逻辑实体,但在 Windows 之外,“驱动器”是一个物理实体,例如磁带驱动器。名称“Win32_LogicalDisk”表明,即使在 Windows 中,磁盘也不总是被视为物理实体。更好的概念是将物理驱动器分成多个逻辑驱动器的分区。 - Sam Hobbs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接