You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取C盘卷序列号突然异常缓慢的问题排查与解决求助

问题:读取C盘卷序列号突然耗时超1分钟

原本正常的C盘卷序列号读取功能突然变慢,日志显示GetHdSerialString方法执行耗时超过1分钟,耗时点集中在获取Win32_LogicalDisk实例的环节。

原实现代码:

public static string GetHdSerialString()
{
    try
    {
        WriteNLog("GetHdSerialString START ", eLogLevel.Info);
        using ManagementClass mangnmt = new ManagementClass("Win32_LogicalDisk");
        using ManagementObjectCollection mcol = mangnmt.GetInstances();
        string result = "";
        foreach (ManagementObject strt in mcol.Cast<ManagementObject>())
        {
            result += Convert.ToString(strt["VolumeSerialNumber"]);
            break; //只取第一个
        }

        result = result.Insert(4, "-");
        WriteNLog("GetHdSerialString END ", eLogLevel.Info);

        return result;
    }
    catch (Exception exc)
    {
        WriteNLog("GetHdSerialString exc:" + exc.Message, eLogLevel.Error);
        return String.Empty;
    }
}

原因分析

  • 原代码通过Win32_LogicalDisk.GetInstances()枚举系统中所有逻辑磁盘,当系统存在离线网络驱动器、未响应的外接存储设备时,WMI会尝试逐一连接这些设备,触发超时等待,这是突然变慢的核心原因。
  • 代码中虽然通过break只取第一个实例,但WMI必须完成所有实例的枚举才会返回集合,因此无法避免前期的枚举耗时。

解决办法

方案1:优化WMI查询(直接定位C盘)

修改WQL查询语句,仅获取C盘的信息,避免枚举所有磁盘:

public static string GetHdSerialString()
{
    try
    {
        WriteNLog("GetHdSerialString START ", eLogLevel.Info);
        string result = "";
        // 直接查询C盘的逻辑磁盘信息
        using ManagementObjectSearcher searcher = new ManagementObjectSearcher(
            "SELECT VolumeSerialNumber FROM Win32_LogicalDisk WHERE DeviceID='C:'");
        foreach (ManagementObject disk in searcher.Get())
        {
            result = Convert.ToString(disk["VolumeSerialNumber"]);
            break;
        }

        if (!string.IsNullOrEmpty(result))
        {
            result = result.Insert(4, "-");
        }
        WriteNLog("GetHdSerialString END ", eLogLevel.Info);

        return result;
    }
    catch (Exception exc)
    {
        WriteNLog("GetHdSerialString exc:" + exc.Message, eLogLevel.Error);
        return String.Empty;
    }
}

方案2:使用Windows原生API(性能更稳定)

调用GetVolumeInformation Win32 API,绕过WMI,彻底避免枚举开销:

using System.Runtime.InteropServices;

public static string GetCVolumeSerial()
{
    try
    {
        WriteNLog("GetCVolumeSerial START ", eLogLevel.Info);
        uint serialNumber = 0;
        // 调用Win32 API获取C盘卷序列号
        if (GetVolumeInformation(@"C:\", null, 0, ref serialNumber, out _, out _, null, 0))
        {
            // 格式化序列号为XXXX-XXXX格式
            string serial = serialNumber.ToString("X8");
            string result = serial.Insert(4, "-");
            WriteNLog("GetCVolumeSerial END ", eLogLevel.Info);
            return result;
        }
        WriteNLog("GetCVolumeSerial: Failed to get serial number", eLogLevel.Error);
        return string.Empty;
    }
    catch (Exception exc)
    {
        WriteNLog("GetCVolumeSerial exc:" + exc.Message, eLogLevel.Error);
        return String.Empty;
    }
}

// 导入Win32 API
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetVolumeInformation(
    string lpRootPathName,
    string lpVolumeNameBuffer,
    uint nVolumeNameSize,
    ref uint lpVolumeSerialNumber,
    out uint lpMaximumComponentLength,
    out uint lpFileSystemFlags,
    string lpFileSystemNameBuffer,
    uint nFileSystemNameSize);

内容的提问来源于stack exchange,提问作者Patrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 13:31:14