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

如何使用C#为虚拟打印机自动化安装XPS类打印机驱动

问题

如何使用C#实现打印机驱动安装向导的自动化操作,为虚拟打印机安装“XPS Class Printer Driver”?

打印机驱动安装向导截图

我已经开发完对应安装程序,实现了虚拟打印机和对应端口的创建,但现在需要用到本机没预装的Microsoft XPS Printer Driver。我可以通过上面截图里的打印机驱动向导手动装完这个驱动,但一直没找到用C#把这个流程自动化的可行方法。
我知道可以调用DRIVER_INFO_6结构体或者Management API做相关操作,但不清楚具体实现步骤。


实现方案

根本不需要模拟向导点击操作,直接调用Windows打印后台处理程序(Win32 Spooler API),指定系统内置的XPS驱动inf路径就能完成安装,比UI模拟稳定得多,不受系统版本、弹窗层级影响。

核心逻辑

  • 微软内置的XPS类驱动默认存放在系统驱动存储里,inf固定路径是C:\Windows\INF\ntprint.inf,驱动自带微软签名,不需要额外下载安装包
  • 调用AddPrinterDriverEx函数,传入填充正确的DRIVER_INFO_6结构体就能完成驱动安装,完全跳过手动向导的点选步骤
  • 驱动装完直接绑定到你已经创建好的虚拟打印机端口就行,不用走系统的添加设备向导

具体实现代码

1. 定义Win32 API和对应结构体

注意区分32位和64位系统的环境适配:

using System;
using System.IO;
using System.Runtime.InteropServices;

public static class SpoolerApi
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct DRIVER_INFO_6
    {
        public uint cVersion;
        [MarshalAs(UnmanagedType.LPTStr)] public string pName;
        [MarshalAs(UnmanagedType.LPTStr)] public string pEnvironment;
        [MarshalAs(UnmanagedType.LPTStr)] public string pDriverPath;
        [MarshalAs(UnmanagedType.LPTStr)] public string pDataFile;
        [MarshalAs(UnmanagedType.LPTStr)] public string pConfigFile;
        [MarshalAs(UnmanagedType.LPTStr)] public string pHelpFile;
        [MarshalAs(UnmanagedType.LPTStr)] public string pDependentFiles;
        [MarshalAs(UnmanagedType.LPTStr)] public string pMonitorName;
        [MarshalAs(UnmanagedType.LPTStr)] public string pDefaultDataType;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszzPreviousNames;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftDriverDate;
        public ulong dwlDriverVersion;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszMfgName;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszOEMUrl;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszHardwareID;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszProvider;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszPrintProcessor;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszVendorSetup;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszzColorProfiles;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszInfPath;
        public uint dwPrinterDriverAttributes;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszzCoreDriverDependencies;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftMinInboxDriverVerDate;
        public ulong dwlMinInboxDriverVerVersion;
    }

    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool AddPrinterDriverEx(
        string pName,
        uint Level,
        ref DRIVER_INFO_6 pDriverInfo,
        uint dwFileCopyFlags);

    public const uint APD_COPY_ALL_FILES = 0x00000004;
    public const uint APD_COPY_FROM_DIRECTORY = 0x00000010;
    public const uint APD_INSTALL_WARNED_DRIVER = 0x00008000;
}

2. 填充驱动参数执行安装

XPS Class Driver的参数都是系统内置固定值,不需要手动选制造商、型号,直接按下面的值填充就行:

public static bool InstallXpsClassDriver()
{
    // 适配系统架构,对应驱动存放路径
    string env = Environment.Is64BitOperatingSystem ? "Windows x64" : "Windows NT x86";
    string driverDir = Environment.Is64BitOperatingSystem 
        ? @"C:\Windows\System32\spool\drivers\x64\3" 
        : @"C:\Windows\System32\spool\drivers\W32X86\3";

    var driverInfo = new SpoolerApi.DRIVER_INFO_6
    {
        cVersion = 3,
        pName = "Microsoft XPS Class Driver",
        pEnvironment = env,
        pDriverPath = Path.Combine(driverDir, "mxdwdrv.dll"),
        pConfigFile = Path.Combine(driverDir, "unidrvui.dll"),
        pDataFile = Path.Combine(driverDir, "xpssvcs.dll"),
        pszInfPath = @"C:\Windows\INF\ntprint.inf",
        pszMfgName = "Microsoft",
        pszHardwareID = "Microsoft_XPS_Class_Driver",
        pszProvider = "Microsoft",
        pszPrintProcessor = "winprint",
        pDefaultDataType = "RAW"
    };

    bool installResult = SpoolerApi.AddPrinterDriverEx(
        null, // 本地机器直接传null
        6, // 对应DRIVER_INFO_6结构体级别
        ref driverInfo,
        SpoolerApi.APD_COPY_ALL_FILES | SpoolerApi.APD_COPY_FROM_DIRECTORY | SpoolerApi.APD_INSTALL_WARNED_DRIVER
    );

    if (!installResult)
    {
        int errCode = Marshal.GetLastWin32Error();
        // 错误码0、1795都代表驱动已经存在,属于正常情况
        if (errCode == 0 || errCode == 1795)
            return true;
        throw new InvalidOperationException($"驱动安装失败,系统错误码:{errCode}");
    }
    return true;
}

3. 绑定驱动到已创建的虚拟打印机

驱动安装完成后,调用AddPrinter或者SetPrinterAPI,把你之前创建的虚拟打印机的驱动名指定为Microsoft XPS Class Driver就完成全部流程了。

踩坑提醒

  • 代码必须以管理员权限运行,安装打印机驱动是系统级操作,记得在程序manifest里配置requireAdministrator权限级别
  • 别折腾UI自动化、模拟键鼠点击那套,Win10、Win11、Server版的向导界面布局、控件ID都不一样,稳定性极差
  • 不推荐用WMI/Management API装打印驱动,WMI对打印模块的封装有很多已知bug,64位系统下经常出权限不足、参数不识别的问题,直接调原生Spooler API是最靠谱的方案
  • 如果是精简版系统删掉了内置ntprint.inf,这个方法会失败,这种情况提前从对应版本的系统镜像里提取内置驱动包,替换代码里的inf路径即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 10:03:37