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

如何获取Windows设备中WMI未返回的打印机型号、序列号等信息?

解决Windows物理打印机型号、序列号获取问题

方案1:通过WMI关联查询硬件设备信息

Win32_Printer偏向打印队列配置,打印机的硬件信息(型号、序列号)通常存储在PnP设备类中。可以通过Win32_PrinterDevice关联类,将打印队列与对应硬件设备绑定,再从Win32_PnPEntity中提取硬件详情。

示例代码

public async Task<List<Printer>> DiscoverPrintersWithHardwareInfo()
{
    List<Printer> printers = new();

    try
    {
        string query = @"
            SELECT 
                p.Name, p.DriverName, 
                pnp.DeviceID, pnp.Description, pnp.SerialNumber, pnp.Model
            FROM 
                Win32_Printer p
                JOIN Win32_PrinterDevice pd ON p.Name = pd.PrinterName
                JOIN Win32_PnPEntity pnp ON pd.DeviceID = pnp.DeviceID
            WHERE 
                p.Local = TRUE OR p.Network = TRUE";

        ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
        foreach (ManagementObject item in searcher.Get())
        {
            var printer = new Printer
            {
                Name = item["Name"]?.ToString(),
                DriverName = item["DriverName"]?.ToString(),
                Model = item["Model"]?.ToString(),
                SerialNumber = item["SerialNumber"]?.ToString(),
                DeviceId = item["DeviceID"]?.ToString()
            };
            printers.Add(printer);
        }
    }
    catch (Exception ex)
    {
        await _databaseService.LogException(ex);
    }

    return printers;
}

注意:部分打印机是否暴露序列号,取决于设备驱动是否上报该信息。

方案2:调用Windows打印后台处理程序API

使用GetPrinter2函数可获取底层打印机信息,其中PRINTER_INFO_9结构体包含设备硬件ID,结合SetupAPI能进一步查询硬件详情。

示例代码思路(C# P/Invoke)

[DllImport("winspool.drv", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool GetPrinter2(
    IntPtr hPrinter,
    int Level,
    IntPtr pPrinterInfo,
    int cbBuf,
    out int pcbNeeded);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct PRINTER_INFO_9
{
    public string pszDeviceName;
}

public string GetPrinterHardwareId(string printerName)
{
    IntPtr hPrinter = IntPtr.Zero;
    if (OpenPrinter(printerName, out hPrinter, IntPtr.Zero))
    {
        try
        {
            int cbNeeded = 0;
            GetPrinter2(hPrinter, 9, IntPtr.Zero, 0, out cbNeeded);
            IntPtr pInfo = Marshal.AllocHGlobal(cbNeeded);
            if (GetPrinter2(hPrinter, 9, pInfo, cbNeeded, out _))
            {
                PRINTER_INFO_9 info = Marshal.PtrToStructure<PRINTER_INFO_9>(pInfo);
                return info.pszDeviceName;
            }
            Marshal.FreeHGlobal(pInfo);
        }
        finally
        {
            ClosePrinter(hPrinter);
        }
    }
    return null;
}

拿到硬件ID后,可使用SetupDiGetDeviceRegistryProperty函数读取设备的序列号(SPDRP_SERIALNUMBER)和型号(SPDRP_FRIENDLYNAME)。

方案3:读取注册表

打印机硬件信息会存在PnP设备的注册表项中,路径通常为HKLM\SYSTEM\CurrentControlSet\Enum\<硬件ID路径>,包含SerialNumber、FriendlyName等值。可通过WMI获取的设备ID拼接路径后读取对应值。

示例代码

public string GetPrinterSerialFromRegistry(string deviceId)
{
    string registryPath = $"SYSTEM\\CurrentControlSet\\Enum\\{deviceId}";
    using (var key = Registry.LocalMachine.OpenSubKey(registryPath))
    {
        return key?.GetValue("SerialNumber")?.ToString();
    }
}

总结

  • 优先尝试方案1,实现简单无需额外P/Invoke;
  • 若方案1无法获取所需信息,再用方案2,能获取最全面的硬件信息,但需处理较多Win32 API调用;
  • 方案3作为补充,适用于特定设备驱动未正确上报信息的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 06:15:12