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

如何在C# WinForms中为选中打印机编程打印Windows测试页

问题描述

我正在构建一个面向Windows 7/10、基于.NET Framework 4.0的C# WinForms应用程序。希望用户能从ComboBox中选择打印机,并为该选中打印机打印标准Windows测试页(即点击“打印机属性→打印测试页”时打印的页面),无需打印自定义文档,仅需内置测试页。

以下是我在ComboBox中列出已安装打印机的代码:

foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
    comboBox_Printers.Items.Add(printer);
}

// 获取选中打印机示例:
string selectedPrinter = comboBox_Printers.SelectedItem?.ToString();

我已尝试以下方法:

  • 使用PrintDocument打印测试页,但它仅支持打印自定义内容,无法打印内置Windows测试页
  • 搜索WMI或PrintServer方法,但未找到触发内置测试页的途径

具体问题

  1. 是否可以在C#中为特定打印机编程触发Windows测试页?
  2. 是否仅使用内置.NET/Windows API就能实现该功能?
  3. 若可以,WinForms应用中的推荐实现方案是什么?

环境

  • Windows 7 / 10
  • .NET Framework 4.0
  • WinForms

解答

1. 可以实现

Windows系统原生支持通过API触发内置测试页打印,完全可以在C#中实现该功能。

2. 仅用内置API即可实现

无需第三方库,通过P/Invoke调用Windows系统的winspool.drv库中的原生API就能完成,完全依赖内置的.NET和Windows系统接口。

3. 推荐实现方案

核心是调用PrintTestPage函数,结合打印机句柄的打开与关闭逻辑,完整实现流程如下:

步骤1:声明P/Invoke接口

在WinForms窗体类中添加以下API声明:

using System.Runtime.InteropServices;

[DllImport("winspool.drv", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool PrintTestPage(IntPtr hPrinter);

[DllImport("winspool.drv", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);

[DllImport("winspool.drv", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool ClosePrinter(IntPtr hPrinter);

步骤2:实现打印测试页方法

编写封装方法,处理打印机句柄的生命周期和测试页打印逻辑:

private void PrintWindowsTestPage(string printerName)
{
    if (string.IsNullOrEmpty(printerName))
    {
        MessageBox.Show("请选择一台打印机");
        return;
    }

    IntPtr printerHandle = IntPtr.Zero;
    try
    {
        // 打开打印机获取句柄
        bool openSuccess = OpenPrinter(printerName, out printerHandle, IntPtr.Zero);
        if (!openSuccess)
        {
            int errorCode = Marshal.GetLastWin32Error();
            MessageBox.Show($"打开打印机失败,错误码:{errorCode}");
            return;
        }

        // 触发测试页打印
        bool printSuccess = PrintTestPage(printerHandle);
        MessageBox.Show(printSuccess ? "测试页打印请求已发送" : $"打印测试页失败,错误码:{Marshal.GetLastWin32Error()}");
    }
    finally
    {
        // 确保关闭打印机句柄,避免资源泄漏
        if (printerHandle != IntPtr.Zero)
        {
            ClosePrinter(printerHandle);
        }
    }
}

步骤3:绑定到UI事件

在打印按钮的点击事件中调用上述方法:

private void btnPrintTestPage_Click(object sender, EventArgs e)
{
    string selectedPrinter = comboBox_Printers.SelectedItem?.ToString();
    PrintWindowsTestPage(selectedPrinter);
}

注意事项

  • 普通用户权限即可完成操作,部分受限制的系统环境可能需要管理员权限;
  • 错误码可通过Marshal.GetLastWin32Error()获取,对应Windows系统标准错误代码,可用于进一步排查问题;
  • 该方案完全兼容Windows 7和Windows 10,符合.NET Framework 4.0的环境要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 18:05:05