如何验证和合并打印票据

Microsoft Windows 打印架构包括灵活且可扩展的PrintCapabilitiesPrintTicket元素。 前者对打印设备的功能进行项化,后者指定设备应如何对文档、单个文档或单个页面的特定序列使用这些功能。

支持打印的应用程序的典型任务序列如下所示。

  1. 确定打印机的功能。

  2. 配置 a PrintTicket 以使用这些功能。

  3. 验证PrintTicket.

本文介绍如何做到这一点。

示例:

在下面的简单示例中,我们仅对打印机是否可以支持双面打印(双面打印)感兴趣。 主要步骤如下。

  1. 使用GetPrintCapabilities方法获取PrintCapabilities对象。

  2. 测试是否存在所需的功能。 在下面的示例中,我们测试 PrintCapabilities 对象的 DuplexingCapability 属性是否具备在纸张两侧打印的能力,并在纸张的长侧进行“翻页”。 由于 DuplexingCapability 是集合,因此我们使用 ReadOnlyCollection<T>Contains 方法。

    注释

    此步骤并非严格必要。 MergeAndValidatePrintTicket方法用于将PrintTicket中的每个请求与打印机的功能进行检查。 如果打印机不支持所请求的功能,打印机驱动程序将在该方法返回PrintTicket时替换为其他请求。

  3. 如果打印机支持双面打印,示例代码将创建一个要求双面的PrintTicket。 但应用程序未在 PrintTicket 元素中指定所有可能的打印机设置。 这将浪费程序员和程序时间。 相反,代码仅设置双工请求,然后将该PrintTicket与现有的、已完全配置和验证过的PrintTicket合并,在本例中,该PrintTicket就是用户的默认PrintTicket

  4. 因此,该示例调用 MergeAndValidatePrintTicket 方法,以将新的、最小的 PrintTicket 与用户的默认 PrintTicket 合并。 返回一个ValidationResult,其中包含将PrintTicket作为其属性之一的新属性。

  5. 然后,该示例测试新的 PrintTicket 是否请求双工。 如果这样做,则该示例使其成为用户的新默认打印票证。 如果省略了上面的步骤 2,且打印机不支持沿长边双面打印,那么测试结果将是 false。 (请参阅上面的说明。

  6. 最后一个重要步骤是使用Commit方法将更改提交到PrintQueueUserPrintTicket属性。

/// <summary>
/// Changes the user-default PrintTicket setting of the specified print queue.
/// </summary>
/// <param name="queue">the printer whose user-default PrintTicket setting needs to be changed</param>
static private void ChangePrintTicketSetting(PrintQueue queue)
{
    //
    // Obtain the printer's PrintCapabilities so we can determine whether or not
    // duplexing printing is supported by the printer.
    //
    PrintCapabilities printcap = queue.GetPrintCapabilities();

    //
    // The printer's duplexing capability is returned as a read-only collection of duplexing options
    // that can be supported by the printer. If the collection returned contains the duplexing
    // option we want to set, it means the duplexing option we want to set is supported by the printer,
    // so we can make the user-default PrintTicket setting change.
    //
    if (printcap.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge))
    {
        //
        // To change the user-default PrintTicket, we can first create a delta PrintTicket with
        // the new duplexing setting.
        //
        PrintTicket deltaTicket = new PrintTicket();
        deltaTicket.Duplexing = Duplexing.TwoSidedLongEdge;

        //
        // Then merge the delta PrintTicket onto the printer's current user-default PrintTicket,
        // and validate the merged PrintTicket to get the new PrintTicket we want to set as the
        // printer's new user-default PrintTicket.
        //
        ValidationResult result = queue.MergeAndValidatePrintTicket(queue.UserPrintTicket, deltaTicket);

        //
        // The duplexing option we want to set could be constrained by other PrintTicket settings
        // or device settings. We can check the validated merged PrintTicket to see whether the
        // the validation process has kept the duplexing option we want to set unchanged.
        //
        if (result.ValidatedPrintTicket.Duplexing == Duplexing.TwoSidedLongEdge)
        {
            //
            // Set the printer's user-default PrintTicket and commit the set operation.
            //
            queue.UserPrintTicket = result.ValidatedPrintTicket;
            queue.Commit();
            Console.WriteLine("PrintTicket new duplexing setting is set on '{0}'.", queue.FullName);
        }
        else
        {
            //
            // The duplexing option we want to set has been changed by the validation process
            // when it was resolving setting constraints.
            //
            Console.WriteLine("PrintTicket new duplexing setting is constrained on '{0}'.", queue.FullName);
        }
    }
    else
    {
        //
        // If the printer doesn't support the duplexing option we want to set, skip it.
        //
        Console.WriteLine("PrintTicket new duplexing setting is not supported on '{0}'.", queue.FullName);
    }
}
''' <summary>
''' Changes the user-default PrintTicket setting of the specified print queue.
''' </summary>
''' <param name="queue">the printer whose user-default PrintTicket setting needs to be changed</param>
Private Shared Sub ChangePrintTicketSetting(ByVal queue As PrintQueue)
    '
    ' Obtain the printer's PrintCapabilities so we can determine whether or not
    ' duplexing printing is supported by the printer.
    '
    Dim printcap As PrintCapabilities = queue.GetPrintCapabilities()

    '
    ' The printer's duplexing capability is returned as a read-only collection of duplexing options
    ' that can be supported by the printer. If the collection returned contains the duplexing
    ' option we want to set, it means the duplexing option we want to set is supported by the printer,
    ' so we can make the user-default PrintTicket setting change.
    '
    If printcap.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) Then
        '
        ' To change the user-default PrintTicket, we can first create a delta PrintTicket with
        ' the new duplexing setting.
        '
        Dim deltaTicket As New PrintTicket()
        deltaTicket.Duplexing = Duplexing.TwoSidedLongEdge

        '
        ' Then merge the delta PrintTicket onto the printer's current user-default PrintTicket,
        ' and validate the merged PrintTicket to get the new PrintTicket we want to set as the
        ' printer's new user-default PrintTicket.
        '
        Dim result As ValidationResult = queue.MergeAndValidatePrintTicket(queue.UserPrintTicket, deltaTicket)

        '
        ' The duplexing option we want to set could be constrained by other PrintTicket settings
        ' or device settings. We can check the validated merged PrintTicket to see whether the
        ' the validation process has kept the duplexing option we want to set unchanged.
        '
        If result.ValidatedPrintTicket.Duplexing = Duplexing.TwoSidedLongEdge Then
            '
            ' Set the printer's user-default PrintTicket and commit the set operation.
            '
            queue.UserPrintTicket = result.ValidatedPrintTicket
            queue.Commit()
            Console.WriteLine("PrintTicket new duplexing setting is set on '{0}'.", queue.FullName)
        Else
            '
            ' The duplexing option we want to set has been changed by the validation process
            ' when it was resolving setting constraints.
            '
            Console.WriteLine("PrintTicket new duplexing setting is constrained on '{0}'.", queue.FullName)
        End If
    Else
        '
        ' If the printer doesn't support the duplexing option we want to set, skip it.
        '
        Console.WriteLine("PrintTicket new duplexing setting is not supported on '{0}'.", queue.FullName)
    End If
End Sub

因此,可以快速测试此示例,下面显示了其余部分。 创建项目和命名空间,然后将本文中的代码片段粘贴到命名空间块中。

/// <summary>
/// Displays the correct command line syntax to run this sample program.
/// </summary>
static private void DisplayUsage()
{
    Console.WriteLine();
    Console.WriteLine("Usage #1: printticket.exe -l \"<printer_name>\"");
    Console.WriteLine("      Run program on the specified local printer");
    Console.WriteLine();
    Console.WriteLine("      Quotation marks may be omitted if there are no spaces in printer_name.");
    Console.WriteLine();
    Console.WriteLine("Usage #2: printticket.exe -r \"\\\\<server_name>\\<printer_name>\"");
    Console.WriteLine("      Run program on the specified network printer");
    Console.WriteLine();
    Console.WriteLine("      Quotation marks may be omitted if there are no spaces in server_name or printer_name.");
    Console.WriteLine();
    Console.WriteLine("Usage #3: printticket.exe -a");
    Console.WriteLine("      Run program on all installed printers");
    Console.WriteLine();
}

[STAThread]
static public void Main(string[] args)
{
    try
    {
        if ((args.Length == 1) && (args[0] == "-a"))
        {
            //
            // Change PrintTicket setting for all local and network printer connections.
            //
            LocalPrintServer server = new LocalPrintServer();

            EnumeratedPrintQueueTypes[] queue_types = {EnumeratedPrintQueueTypes.Local,
                                                       EnumeratedPrintQueueTypes.Connections};

            //
            // Enumerate through all the printers.
            //
            foreach (PrintQueue queue in server.GetPrintQueues(queue_types))
            {
                //
                // Change the PrintTicket setting queue by queue.
                //
                ChangePrintTicketSetting(queue);
            }
        }//end if -a

        else if ((args.Length == 2) && (args[0] == "-l"))
        {
            //
            // Change PrintTicket setting only for the specified local printer.
            //
            LocalPrintServer server = new LocalPrintServer();
            PrintQueue queue = new PrintQueue(server, args[1]);
            ChangePrintTicketSetting(queue);
        }//end if -l

        else if ((args.Length == 2) && (args[0] == "-r"))
        {
            //
            // Change PrintTicket setting only for the specified remote printer.
            //
            String serverName = args[1].Remove(args[1].LastIndexOf(@"\"));
            String printerName = args[1].Remove(0, args[1].LastIndexOf(@"\")+1);
            PrintServer ps = new PrintServer(serverName);
            PrintQueue queue = new PrintQueue(ps, printerName);
            ChangePrintTicketSetting(queue);
         }//end if -r

        else
        {
            //
            // Unrecognized command line.
            // Show user the correct command line syntax to run this sample program.
            //
            DisplayUsage();
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
        Console.WriteLine(e.StackTrace);

        //
        // Show inner exception information if it's provided.
        //
        if (e.InnerException != null)
        {
            Console.WriteLine("--- Inner Exception ---");
            Console.WriteLine(e.InnerException.Message);
            Console.WriteLine(e.InnerException.StackTrace);
        }
    }
    finally
    {
        Console.WriteLine("Press Return to continue...");
        Console.ReadLine();
    }
}//end Main
''' <summary>
''' Displays the correct command line syntax to run this sample program.
''' </summary>
Private Shared Sub DisplayUsage()
    Console.WriteLine()
    Console.WriteLine("Usage #1: printticket.exe -l ""<printer_name>""")
    Console.WriteLine("      Run program on the specified local printer")
    Console.WriteLine()
    Console.WriteLine("      Quotation marks may be omitted if there are no spaces in printer_name.")
    Console.WriteLine()
    Console.WriteLine("Usage #2: printticket.exe -r ""\\<server_name>\<printer_name>""")
    Console.WriteLine("      Run program on the specified network printer")
    Console.WriteLine()
    Console.WriteLine("      Quotation marks may be omitted if there are no spaces in server_name or printer_name.")
    Console.WriteLine()
    Console.WriteLine("Usage #3: printticket.exe -a")
    Console.WriteLine("      Run program on all installed printers")
    Console.WriteLine()
End Sub


<STAThread>
Public Shared Sub Main(ByVal args() As String)
    Try
        If (args.Length = 1) AndAlso (args(0) = "-a") Then
            '
            ' Change PrintTicket setting for all local and network printer connections.
            '
            Dim server As New LocalPrintServer()

            Dim queue_types() As EnumeratedPrintQueueTypes = {EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections}

            '
            ' Enumerate through all the printers.
            '
            For Each queue As PrintQueue In server.GetPrintQueues(queue_types)
                '
                ' Change the PrintTicket setting queue by queue.
                '
                ChangePrintTicketSetting(queue)
            Next queue 'end if -a

        ElseIf (args.Length = 2) AndAlso (args(0) = "-l") Then
            '
            ' Change PrintTicket setting only for the specified local printer.
            '
            Dim server As New LocalPrintServer()
            Dim queue As New PrintQueue(server, args(1))
            ChangePrintTicketSetting(queue) 'end if -l

        ElseIf (args.Length = 2) AndAlso (args(0) = "-r") Then
            '
            ' Change PrintTicket setting only for the specified remote printer.
            '
            Dim serverName As String = args(1).Remove(args(1).LastIndexOf("\"))
            Dim printerName As String = args(1).Remove(0, args(1).LastIndexOf("\")+1)
            Dim ps As New PrintServer(serverName)
            Dim queue As New PrintQueue(ps, printerName)
            ChangePrintTicketSetting(queue) 'end if -r

        Else
            '
            ' Unrecognized command line.
            ' Show user the correct command line syntax to run this sample program.
            '
            DisplayUsage()
        End If
    Catch e As Exception
        Console.WriteLine(e.Message)
        Console.WriteLine(e.StackTrace)

        '
        ' Show inner exception information if it's provided.
        '
        If e.InnerException IsNot Nothing Then
            Console.WriteLine("--- Inner Exception ---")
            Console.WriteLine(e.InnerException.Message)
            Console.WriteLine(e.InnerException.StackTrace)
        End If
    Finally
        Console.WriteLine("Press Return to continue...")
        Console.ReadLine()
    End Try
End Sub

另请参阅