.Net Core 2.1中获取USB存储设备的序列号 [英] Get the serial number of USB storage devices in .Net Core 2.1

查看:24
本文介绍了.Net Core 2.1中获取USB存储设备的序列号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获取.Net Core 2.1中USB存储设备的序列号?

How can I get the serial number of USB storage devices in .Net Core 2.1?

我找到了不同的解决方案,但遗憾的是,由于 .Net Core 中缺少 Windows 注册表和 WMI 支持,它们不起作用.

I found different solutions, but sadly they don't work due the lack of Windows registry and WMI support in .Net Core.

在 Powershell 中它真的很简单,但我无法在 Powershell Core 中找到实现.

In Powershell it's really simple, but I wasn't able to find an implementation in Powershell Core.

PS C:> Get-Disk | Select-Object SerialNumber

SerialNumber
------------
0008_0D02_0021_9852.

我更喜欢对客户端(Win、Linux、Mac)没有额外安装要求的解决方案.

I prefer a solution with no extra installation requirements on the clients (Win, Linux, Mac).

推荐答案

此类对 WMI Win32_DiskDrive 类及其关联器:Win32_DiskDriveToDiskPartitionCIM_LogicalDiskBasedOnPartition,用于检索系统(本地或远程)上活动 USB 驱动器的信息.

This Class performs a series of queries on the WMI Win32_DiskDrive class and its associators: Win32_DiskDriveToDiskPartition and CIM_LogicalDiskBasedOnPartition, to retrieve informations on the active USB Drives on a System (local or remote).

这似乎是多余的(可能是因为它是),因为您只是要求提供 USB 驱动器序列号.但是,您永远不知道接下来需要什么,而且它可能对其他人有用.

It might seem redundant (probably because it is), since you just asked for the USB Drives Serial Number. But, you never know what you will need next, and it could be useful to someone else.

它需要 Microsoft .Net System.Management 4.5 用于 .Net Core 2.1(NuGet 包)
可以使用 Visual Studio NuGet 包管理器轻松找到并安装.
关于 Linux 支持,请阅读此处:
Windows Management Instrumentation 现在是 Linux 4.13 的正式总线

It requires Microsoft .Net System.Management 4.5 for .Net Core 2.1 (NuGet Package)
Can be easily found and installed using the Visual Studio NuGet Package Manager.
About Linux support, read here:
Windows Management Instrumentation Now A Formal Bus With Linux 4.13

另外,请留意 Windows .NET Core 兼容包.
不断添加和更新新的跨平台程序集.

Also, keep an eye out for Windows Compatibility Pack for .NET Core.
New cross-platform assemblies are constantly added and updated.

主类实现了所有必需的功能,并且结构非常简单.
WMI 查询使用关联器语法,这是一种关联 WMI 类对象的方法.
类属性的含义不言自明.

The main class implements all the required functionalities and it has quite a simple structure.
The WMI queries use the Associator syntax, a method to correlate WMI class objects related to each other.
The Class properties meaning is self-explanatory.

可以这样实例化:
SystemUSBDrives systemUSBDrives = new SystemUSBDrives("[计算机名称]");

Can be instantiated this way:
SystemUSBDrives systemUSBDrives = new SystemUSBDrives("[Computer Name]");

[Computer Name]为空或为空时,使用本地机器名.

When [Computer Name] is null or empty, it uses the Local Machine name.

要获取 USB 设备列表及其属性,请调用 GetUSBDrivesInfo() 方法:

To get the List of USB Devices and their properties, call the GetUSBDrivesInfo() method:

var USBDrivesEnum = systemUSBDrives.GetUSBDrivesInfo([UserName], [Password], [Domain]);

[UserName], [Password], [Domain] 用于连接到 NT 域.
如果不需要,这些参数可以为 null 或空字符串.

[UserName], [Password], [Domain] are used to connect to a NT Domain.
These parameters, if not needed, can be null or an empty string.

示例类实例化和函数调用(Local Machine, no authentication):

SystemUSBDrives systemUSBDrives = new SystemUSBDrives(null);
var USBDrivesEnum = systemUSBDrives.GetUSBDrivesInfo(null, null, null);


测试对象:
Visual Studio Pro 15.7.6 - 15.9.35
.Net Core 2.1/.Net Framework 4.8
<代码>C# 6.0 ->7.3
.Net System.Management 4.5

using System.Management;

public class SystemUSBDrives
{
    string m_ComputerName = string.Empty;
    public SystemUSBDrives(string ComputerName) {
        this.m_ComputerName = string.IsNullOrEmpty(ComputerName)
                            ? Environment.MachineName
                            : ComputerName;
    }

    private static EnumerationOptions GetEnumerationOptions(bool DeepScan)
    {
        var mOptions = new EnumerationOptions()
        {
            Rewindable = false,        //Forward only query => no caching
            ReturnImmediately = true,  //Pseudo-async result
            DirectRead = true,
            EnumerateDeep = DeepScan
        };
        return mOptions;
    }

    private static ConnectionOptions GetConnectionOptions() => GetConnectionOptions("", "", "");

    private static ConnectionOptions GetConnectionOptions(string userName, string password, string domain)
    {
        var connOptions = new ConnectionOptions()
        {
            EnablePrivileges = true,
            Timeout = ManagementOptions.InfiniteTimeout,
            Authentication = AuthenticationLevel.PacketPrivacy,
            Impersonation = ImpersonationLevel.Impersonate,
            Username = userName,
            Password = password,
            Authority = !string.IsNullOrEmpty(Domain) ? $"NTLMDOMAIN:{domain}" : string.Empty  //Authority = "NTLMDOMAIN:[domain]"
        };
        return connOptions;
    }

    public List<USBDriveInfo> GetUSBDrivesInfo(string userName, string password, string domain)
    {
        var wmiQueryResult = new List<USBDriveInfo>();
        ConnectionOptions connOptions = GetConnectionOptions(userName, password, domain);
        EnumerationOptions mOptions = GetEnumerationOptions(false);
        var mScope = new ManagementScope($@"\{this.m_ComputerName}
ootCIMV2", connOptions);
        var selQuery = new SelectQuery("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
        mScope.Connect();

        using (var moSearcher = new ManagementObjectSearcher(mScope, selQuery, mOptions)) {
            foreach (ManagementObject moDiskDrive in moSearcher.Get()) {
                var usbInfo = new USBDriveInfo();
                usbInfo.GetDiskDriveInfo(moDiskDrive);

                var relQuery = new RelatedObjectQuery(
                    $"Associators of {{Win32_DiskDrive.DeviceID='{moDiskDrive.Properties["DeviceID"].Value}'}} " +
                    $"WHERE AssocClass = Win32_DiskDriveToDiskPartition");
                using (var moAssocPart = new ManagementObjectSearcher(mScope, relQuery, mOptions)) {
                    foreach (ManagementObject moAssocPartition in moAssocPart.Get()) {

                        usbInfo.GetDiskPartitionInfo(moAssocPartition);
                        relQuery = new RelatedObjectQuery(
                            $"Associators of {{Win32_DiskPartition.DeviceID='{moAssocPartition.Properties["DeviceID"].Value}'}} " +
                            $"WHERE AssocClass = CIM_LogicalDiskBasedOnPartition");

                        using (var moLogDisk = new ManagementObjectSearcher(mScope, relQuery, mOptions)) {
                            foreach (ManagementObject moLogDiskEnu in moLogDisk.Get()) {
                                usbInfo.GetLogicalDiskInfo(moLogDiskEnu);
                                moLogDiskEnu.Dispose();
                            }
                        }
                        moAssocPartition.Dispose();
                    }
                    wmiQueryResult.Add(usbInfo);
                }
                moDiskDrive.Dispose();
            }
            return wmiQueryResult;
        }
    }   //GetUSBDrivesInfo()

    public class USBDriveInfo
    {
        private int m_PartionsCount = 0;
        public USBDriveInfo() => this.Partitions = new List<Partition>(1);
        public string Caption { get; private set; }
        public string DeviceID { get; private set; }
        public string FirmwareRevision { get; private set; }
        public ulong FreeSpace { get; private set; }
        public string InterfaceType { get; private set; }
        public bool MediaLoaded { get; private set; }
        public string MediaType { get; private set; }
        public string Model { get; private set; }
        public uint NumberOfPartitions { get; private set; }
        public List<Partition> Partitions { get; private set; }
        public string PNPDeviceID { get; private set; }
        public string SerialNumber { get; private set; }
        public ulong Size { get; private set; }
        public string Status { get; private set; }
        public ulong TotalCylinders { get; private set; }
        public uint TotalHeads { get; private set; }
        public ulong TotalSectors { get; private set; }
        public ulong TotalTracks { get; private set; }
        public uint TracksPerCylinder { get; private set; }

        public class Partition
        {
            public Partition() => this.LogicalDisks = new List<LogicalDisk>();
            public bool Bootable { get; internal set; }
            public bool BootPartition { get; internal set; }
            public uint DiskIndex { get; internal set; }
            public List<LogicalDisk> LogicalDisks { get; internal set; }
            public ulong PartitionBlockSize { get; internal set; }
            public ulong PartitionNumberOfBlocks { get; internal set; }
            public ulong PartitionStartingOffset { get; internal set; }
            public bool PrimaryPartition { get; internal set; }
        }

        public class LogicalDisk
        {
            public ulong FreeSpace { get; internal set; }
            public string FileSystem { get; internal set; }
            public string LogicalDiskVolume { get; internal set; }
            public bool SupportsDiskQuotas { get; internal set; }
            public string VolumeName { get; internal set; }
            public string VolumeSerialNumber { get; internal set; }
        }

        internal void GetDiskDriveInfo(ManagementObject DiskDrive)
        {
            this.Caption = DiskDrive.GetPropertyValue("Caption")?.ToString();
            this.DeviceID = DiskDrive["DeviceID"]?.ToString();
            this.FirmwareRevision = DiskDrive["FirmwareRevision"]?.ToString();
            this.InterfaceType = DiskDrive["InterfaceType"]?.ToString();
            this.MediaLoaded = (bool?)DiskDrive["MediaLoaded"] ?? false;
            this.MediaType = DiskDrive["MediaType"]?.ToString();
            this.Model = DiskDrive["Model"]?.ToString();
            this.NumberOfPartitions = (uint?)DiskDrive["Partitions"] ?? 0;
            this.PNPDeviceID = DiskDrive["PNPDeviceID"]?.ToString();
            this.SerialNumber = DiskDrive["SerialNumber"]?.ToString();
            this.Size = (ulong?)DiskDrive["Size"] ?? 0L;
            this.Status = DiskDrive["Status"]?.ToString();
            this.TotalCylinders = (ulong?)DiskDrive["TotalCylinders"] ?? 0;
            this.TotalHeads = (uint?)DiskDrive["TotalHeads"] ?? 0U;
            this.TotalSectors = (ulong?)DiskDrive["TotalSectors"] ?? 0;
            this.TotalTracks = (ulong?)DiskDrive["TotalTracks"] ?? 0;
            this.TracksPerCylinder = (uint?)DiskDrive["TracksPerCylinder"] ?? 0;
        }

        internal void GetDiskPartitionInfo(ManagementObject Partitions)
        {
            m_PartionsCount += 1;
            this.Partitions.Add(new Partition()
            {
                DiskIndex = (uint?)Partitions["DiskIndex"] ?? 0,
                PartitionBlockSize = (ulong?)Partitions["BlockSize"] ?? 0,
                Bootable = (bool?)Partitions["Bootable"] ?? false,
                BootPartition = (bool?)Partitions["BootPartition"] ?? false,
                PartitionNumberOfBlocks = (ulong?)Partitions["NumberOfBlocks"] ?? 0,
                PrimaryPartition = (bool?)Partitions["PrimaryPartition"] ?? false,
                PartitionStartingOffset = (ulong?)Partitions["StartingOffset"] ?? 0
            });
        }

        internal void GetLogicalDiskInfo(ManagementObject LogicalDisk)
        {
            if (m_PartionsCount == 0) return;
            this.Partitions[m_PartionsCount - 1].LogicalDisks.Add(new LogicalDisk()
            {
                FileSystem = LogicalDisk["FileSystem"]?.ToString(),
                FreeSpace = (ulong?)LogicalDisk["FreeSpace"] ?? 0,
                LogicalDiskVolume = LogicalDisk["DeviceID"]?.ToString(),
                SupportsDiskQuotas = (bool?)LogicalDisk["SupportsDiskQuotas"] ?? false,
                VolumeName = LogicalDisk["VolumeName"]?.ToString(),
                VolumeSerialNumber = LogicalDisk["VolumeSerialNumber"]?.ToString()
            });
            //Linq's Sum() does not sum ulong(s)
            foreach(Partition p in this.Partitions)
            {
                foreach (LogicalDisk ld in p.LogicalDisks) {
                    this.FreeSpace += ld.FreeSpace;
                }
            }
        }
    }
} // SystemUSBDrives

这篇关于.Net Core 2.1中获取USB存储设备的序列号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆