Bagikan melalui


Panduan desain API Print Support Application v3

Artikel ini menyediakan panduan dan contoh untuk OEM printer dan IHV yang menerapkan Aplikasi Dukungan Cetak v3 (PSA) untuk perangkat mereka.

Terminologi

Istilah Definisi
PSA Cetak Aplikasi Dukungan. Aplikasi UWP yang menggunakan API dalam dokumen ini.
IPP Protokol Pencetakan Internet. Digunakan dari perangkat klien untuk berinteraksi dengan printer untuk mengambil dan mengatur preferensi pencetakan dan mengirim dokumen yang akan dicetak.
Dukungan Cetak untuk Printer Terkait Printer IPP fisik yang ditautkan ke PSA.
IPP Printer Printer yang mendukung protokol IPP.
PDL Bahasa deskripsi halaman. Format di mana dokumen dikirim ke printer.
Printer PSA yang Berhubungan Printer IPP fisik yang terkait dengan aplikasi PSA.
Kemampuan Perangkat Cetak Format dokumen XML untuk menentukan kemampuan printer.
PrintSupportExtension Tugas latar belakang PSA yang bertanggung jawab untuk menyediakan kemampuan perluasan batasan printer.

Artikel ini berisi ekstensi v3 ke API publik Aplikasi Dukungan Cetak yang ada yang dijelaskan dalam panduan desain aplikasi dukungan Cetak dan Windows.Graphics.Printing.PrintSupport Namespace. API PSA memungkinkan produsen printer mengembangkan aplikasi dukungan perangkat keras yang dapat meningkatkan pengalaman cetak pengguna Windows saat menggunakan Driver Kelas Microsoft IPP bawaan tanpa perlu mengembangkan driver kustom. Komponen pencetakan berkomunikasi dengan aplikasi PSA melalui proses broker PSA.

Untuk informasi selengkapnya, lihat artikel berikut ini:

Topik Deskripsi
panduan desain Aplikasi Dukungan Cetak Memberikan panduan dan contoh untuk OEM printer dan IHV yang menerapkan aplikasi dukungan cetak (PSA) untuk perangkat mereka.
Panduan desain API untuk Print Support App v4 Memberikan panduan dan contoh untuk OEM printer dan IHV yang mengimplementasikan Aplikasi Dukungan Cetak (PSA) v4 untuk perangkat mereka.
Spesifikasi Manifes MSIX untuk Dukungan Cetak Printer Virtual Menyediakan panduan dan contoh manifes MSIX untuk OEM printer dan IHV yang menerapkan Dukungan Cetak Printer Virtual.
asosiasi aplikasi dukungan cetak Menyediakan panduan dan contoh untuk mengaitkan aplikasi dukungan cetak (PSA) dengan printer.

Ekstensi signifikan ke API adalah sebagai berikut:

  • Kompresi IPP - PSA v3 API menambahkan fitur untuk meningkatkan pencetakan IPP dengan menambahkan fitur kompresi IPP pada pekerjaan cetak untuk printer IPP yang mendukungnya. Beberapa PSA mungkin memiliki kompresi kustom, yang berarti pekerjaan IPP memiliki kompresi ganda yang memengaruhi performa. Untuk mengurangi hal ini, API PSA v3 memperkenalkan properti IsIppCompressionEnabled dan fungsi DisableIppCompressionForJob (untuk menonaktifkan kompresi untuk pekerjaan saat ini jika diperlukan) di kelas runtime PrintWorkflowJobStartingEventArgs (PSA v1 API).

  • Penanganan Kesalahan Pekerjaan IPP dan Error Toast - PSA v3 API memperkenalkan peristiwa JobIssueDetected dalam kelas runtime PrintWorkflowJobBackgroundSession (PSA v1 API). Peristiwa akan muncul setiap kali PSA mendeteksi kesalahan atau peringatan dalam pekerjaan cetak. PSA kemudian bertanggung jawab untuk menunjukkan pesan kesalahan kepada pengguna. Ketika PSA mendaftar dalam acara ini dan mengatur properti SkipSystemErrorToast menjadi benar di PrintWorkflowJobIssueDetectedEventArgs, hal ini memberi tahu sistem pencetakan untuk tidak menampilkan toast sistem pencetakan Windows. API PSA v3 juga menyediakan mekanisme bagi PSA untuk meluncurkan UI ketika pengguna berinteraksi dengan roti panggang.

  • Kustom batas waktu komunikasi IPP - PSA v3 API menyediakan sarana bagi PSA untuk mengatur ulang batas waktu IPP. Selain itu, kelas runtime PrintSupportIppCommunicationConfiguration ditambahkan ke PrintSupportPrintDeviceCapabilitiesChangedEventArgs untuk memanipulasi batas waktu komunikasi IPP. Selain itu, API PSA v3 memperkenalkan event, yang dipicu ketika ada kesalahan dengan komunikasi IPP. Peristiwa ini diperkenalkan sehingga IHV dapat menyelidiki kegagalan dan menyesuaikan nilai batas waktu yang sesuai.

  • Mendukung IPPFaxOut - PSA v3 API menambahkan fitur ke sistem cetak untuk mendukung printer IPPFaxOut. Untuk mendukung Faks, PSA mendukung filter render untuk mengonversi XPS ke Tiff. Karena PSA mungkin memanipulasi konten XPS sebelum mengonversi ke TIFF, PSA menyediakan nilai enum XpsToTiff dalam PrintWorkflowPdlConversionType sehingga PSA dapat memiliki akses ke XPS ke konverter TIFF. Selain itu, menyediakan properti IsIPPFaxOutPrinter pada kelas runtime IppPrintDevice sehingga PSA dapat membedakan antara printer standar dan printer IPPFaxOut.

Menonaktifkan kompresi IPP

Kompresi IPP ditampilkan dalam sampel kode berikut.

public sealed class PrintSupportWorkflowBackgroundTask : IBackgroundTask
{
    public BackgroundTaskDeferral TaskInstanceDeferral { get; set; }
    private PrintWorkflowJobBackgroundSession session;

    public void Run(IBackgroundTaskInstance taskInstance)
    {
        TaskInstanceDeferral = taskInstance.GetDeferral();

        if (taskInstance.TriggerDetails is PrintWorkflowJobTriggerDetails jobDetails)
        {
            session = jobDetails.PrintWorkflowJobSession;
            session.JobStarting += OnJobStarting;
            session.PdlModificationRequested += OnPdlModificationRequested;
            session.JobIssueDetected += OnJobIssueDetected;

            // Make sure to register all the event handlers before PrintWorkflowJobBackgroundSession.Start is called.
            session.Start();
        }
    }

    private void OnJobStarting(PrintWorkflowJobBackgroundSession sender, PrintWorkflowJobStartingEventArgs args)
    {
        using (args.GetDeferral())
        {
            // Skip system rendering.
            args.SetSkipSystemRendering();

            // If Ipp compression is enabled by the system, check to see if PSA does custom compression for the printer
            // and disable system compression if required.
            if (args.IsIppCompressionEnabled)
            {
                if (this.HasCustomCompression(args.Printer))
                {
                    args.DisableIppCompressionForJob();
                }
            }
        }
    }

    bool HasCustomCompression(IppPrintDevice device)
    {
        bool hasCustomCompression = false;
        // Check if the PSA does custom compression for the printer
        return hasCustomCompression;
    } 
} 

Penanganan kesalahan pekerjaan IPP

Sampel ini menunjukkan bagaimana aplikasi PSA dapat mendaftarkan kesalahan pekerjaan, menampilkan pemberitahuan kesalahan pekerjaan, dan meluncurkan UI ketika pengguna mengaktifkan pemberitahuan tersebut.

public sealed class PrintSupportWorkflowBackgroundTask : IBackgroundTask
{
    public BackgroundTaskDeferral TaskInstanceDeferral { get; set; }
    private PrintWorkflowJobBackgroundSession session;

    public void Run(IBackgroundTaskInstance taskInstance)
    {
        TaskInstanceDeferral = taskInstance.GetDeferral();

        if (taskInstance.TriggerDetails is PrintWorkflowJobTriggerDetails jobDetails)
        {
            session = jobDetails.PrintWorkflowJobSession;
            session.JobStarting += OnJobStarting;
            session.PdlModificationRequested += OnPdlModificationRequested;
            session.JobIssueDetected += OnJobIssueDetected;

            // Make sure to register all the event handlers before PrintWorkflowJobBackgroundSession.Start is called.
            session.Start();
        }
    }

    private void OnJobIssueDetected (PrintWorkflowJobBackgroundSession sender, PrintWorkflowJobIssueDetectedEventArgs args)
    {
        // Using a deferral to exclude the background process from being suspended while PSA displays UI.
        Deferral deferral = args.GetDeferral();
        var toast = new ToastNotification(GetErrorToastXml(args.ExtendedError,
                args.JobIssueKind, args.PrinterJob, args.Configuration));
        toast.Activated += async (toastSender, e) =>
        {
            // PSA UI application 
            PrintWorkflowUICompletionStatus uiStatus = await args.UILauncher.LaunchAndCompleteUIAsync();
            // Complete deferral
            deferral.Complete();
        };
        toast.Dismissed += async (toastSender, e) => { deferral.Complete(); };
        toast.Failed += async (toastSender, e) => { deferral.Complete(); };
            
        ToastNotificationManager.CreateToastNotifier().Show(toast);
        args.SkipSystemErrorToast = true;
    }

    private XmlDocument GetErrorToastXml(Exception jobError, PrintWorkflowJobIssueKind issueKind,
        PrintWorkflowPrinterJob printerJob, PrintWorkflowConfiguration workflowConfig )
    {
        var errorToastXml = new XmlDocument();
        // Generate Toast XML based on error information from Exception and PrintWorkflowPrinterJob.
        return errorToastXml;
    }
}

Mengatur batas waktu komunikasi IPP

Sampel ini menunjukkan cara mengatur batas waktu komunikasi IPP.

public sealed class PrintSupportExtensionBackGroundTask : IBackgroundTask
{
    public BackgroundTaskDeferral TaskInstanceDeferral { get; set; }
    private PrintSupportExtensionSession session;

    public void Run(IBackgroundTaskInstance taskInstance)
    {
        taskInstance.Canceled += OnTaskInstanceCanceled;
        TaskInstanceDeferral = taskInstance.GetDeferral();

        if (taskInstance.TriggerDetails is PrintSupportExtensionTriggerDetails extensionDetails)
        {
            session = extensionDetails.Session;
            session.PrintTicketValidationRequested += OnSessionPrintTicketValidationRequested;
            session.PrintDeviceCapabilitiesChanged += OnSessionPrintDeviceCapabilitiesChanged;
            session.CommunicationErrorDetected += OnCommunicationErrorDetected;

            // Make sure to register all the event handlers before PrintSupportExtensionSession.Start is called.
            session.Start();
        }
    }

    private void OnTaskInstanceCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
    {
        session = null;
        TaskInstanceDeferral.Complete();
    }
    
    private void OnSessionPrintDeviceCapabilitiesChanged(PrintSupportExtensionSession sender, PrintSupportPrintDeviceCapabilitiesChangedEventArgs args)
    {
        // Using deferral to exclude the background process from being suspended while PSA updates the printer PDC and other configurations.
        using (args.GetDeferral())
        {
            if (args.CommunicationConfiguration.CanModifyTimeouts)
                {
                    this.UpdateAttributeTimeouts(args.CommunicationConfiguration, sender.Printer);
                    this.UpdateJobTimeouts(args.CommunicationConfiguration, sender.Printer);
                }
                // Do other operations, such as Updating PDC, PDR, and so on here.
        }
    }

    void UpdateAttributeTimeouts(PrintSupportIppCommunicationConfiguration config, IppPrintDevice device)
    {
        IppPrinterCommunicationKind communicationKind = config.CommunicationKind;
        PrintSupportIppCommunicationTimeouts currentTimeouts = config.IppAttributeTimeouts;

        // Adjust attribute timeouts based on the printer
        switch (communicationKind)
        {
            case IppPrinterCommunicationKind.Network:
                currentTimeouts.ConnectTimeout = TimeSpan.FromSeconds(10);
                currentTimeouts.SendTimeout = TimeSpan.FromSeconds(10);
                currentTimeouts.ReceiveTimeout = TimeSpan.FromSeconds(10);
                break;
            case IppPrinterCommunicationKind.UniversalPrint:
                // adjust timeout for universal printer
                break;
        }
        
    }

    void UpdateJobTimeouts(
        PrintSupportIppCommunicationConfiguration config, IppPrintDevice device)
    {
        IppPrinterCommunicationKind communicationKind = config.CommunicationKind;
        PrintSupportIppCommunicationTimeouts currentTimeouts = config.IppJobTimeouts;
        // Adjust job timeouts based on the printer and communication type
        switch (communicationKind)
        {
            case IppPrinterCommunicationKind.Network:
                currentTimeouts.ConnectTimeout = TimeSpan.FromSeconds(30);
                currentTimeouts.SendTimeout = TimeSpan.FromSeconds(30);
                currentTimeouts.ReceiveTimeout = TimeSpan.FromSeconds(30);
                break;
            case IppPrinterCommunicationKind.UniversalPrint:
                // adjust timeout for universal printer
                break;
        }
    }
}

Menangani kesalahan komunikasi IPP

Sampel ini menunjukkan cara menangani kesalahan komunikasi IPP.

public sealed class PrintSupportExtensionBackGroundTask : IBackgroundTask
{
    public BackgroundTaskDeferral TaskInstanceDeferral { get; set; }
    private PrintSupportExtensionSession session;
    public void Run(IBackgroundTaskInstance taskInstance)
    {
        taskInstance.Canceled += OnTaskInstanceCanceled;
        TaskInstanceDeferral = taskInstance.GetDeferral();

        if (taskInstance.TriggerDetails is PrintSupportExtensionTriggerDetails extensionDetails)
        {
            session = extensionDetails.Session;
            session.PrintTicketValidationRequested += OnSessionPrintTicketValidationRequested;
            session.PrintDeviceCapabilitiesChanged += OnSessionPrintDeviceCapabilitiesChanged;
            session.CommunicationErrorDetected += OnCommunicationErrorDetected ;

            // Make sure to register all the event handlers before PrintSupportExtensionSession.Start is called.
            session.Start();
        }
    }

    private void OnTaskInstanceCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
    {
        session = null;
        TaskInstanceDeferral.Complete();
    }

    private void OnCommunicationErrorDetected(PrintSupportExtensionSession sender, PrintSupportCommunicationErrorDetectedEventArgs args)
    {
        // Using deferral to exclude the background process from being suspended while PSA updates the timeouts.
        using (args.GetDeferral())
        {

            if (args.ErrorKind == IppCommunicationErrorKind.Timeout)
            {
                PrintSupportIppCommunicationConfiguration ippConfig = args.CommunicationConfiguration;
                IppPrintDevice device = sender.Printer;
                // Update timeout based on the communication error
            }
        }
    }  
}

Mencetak ke printer faks IPP di PSA

Sampel ini menunjukkan cara mencetak menggunakan printer IPPFaxOut di PSA.

public sealed class PrintSupportWorkflowBackgroundTask : IBackgroundTask
{
    public BackgroundTaskDeferral TaskInstanceDeferral { get; set; }
    private PrintWorkflowJobBackgroundSession session;

    public void Run(IBackgroundTaskInstance taskInstance)
    {
        TaskInstanceDeferral = taskInstance.GetDeferral();

        if (taskInstance.TriggerDetails is PrintWorkflowJobTriggerDetails jobDetails)
        {
            session = jobDetails.PrintWorkflowJobSession;
            session.JobStarting += OnJobStarting;
            session.PdlModificationRequested += OnPdlModificationRequested;
            session.JobIssueDetected += OnJobIssueDetected;

            // Make sure to register all the event handlers before PrintWorkflowJobBackgroundSession.Start is called.
            session.Start();
        }
    }

    private async void OnPdlModificationRequested(PrintWorkflowJobBackgroundSession sender, PrintWorkflowPdlModificationRequestedEventArgs args)
    {
        using (args.GetDeferral())
        {
            IppPrintDevice printer = args.PrinterJob.Printer;
            IInputStream xpsContent = args.SourceContent.GetInputStream();
            WorkflowPrintTicket printTicket = args.PrinterJob.GetJobPrintTicket();

            string documentFormat = this.GetPrinterDocumentFormat(printer);
            PrintWorkflowPdlTargetStream targetStream = args.CreateJobOnPrinter(documentFormat);
            IInputStream xpsSourceContent = xpsContent;
            if (printer.IsIPPFaxOutPrinter)
            {                    
                // Add cover page to XPS source document   
                xpsSourceContent = this.AddCoverPageToXpsContent(xpsContent);
            }
            
            PrintWorkflowPdlConverter pdlConverter;
            switch (documentFormat.ToLowerInvariant())
            {
                case "image/pwg-raster":
                    pdlConverter = args.GetPdlConverter(PrintWorkflowPdlConversionType.XpsToPwgr);
                    break;
                case "application/pclm":
                    pdlConverter = args.GetPdlConverter(PrintWorkflowPdlConversionType.XpsToPclm);
                    break;
                case "application/pdf":
                    pdlConverter = args.GetPdlConverter(PrintWorkflowPdlConversionType.XpsToPdf);
                    break;
                case "image/tiff":
                    pdlConverter = args.GetPdlConverter(PrintWorkflowPdlConversionType.XpsToTiff);
                    break;
                default:
                    // This should not happen, aborting workflow if PSA does not identify the supported PDLs
                    args.Configuration.AbortPrintFlow(PrintWorkflowJobAbortReason.JobFailed);
                    return;
                }
                // Use pdlConverter to convert the source XPS stream to printer's document format and send it to the printer using targetStream.
                await pdlConverter.ConvertPdlAsync(printTicket, xpsSourceContent, targetStream.GetOutputStream());

                targetStream.CompleteStreamSubmission(PrintWorkflowSubmittedStatus.Succeeded);
            }
        }

    private IInputStream AddCoverPageToXpsContent(IInputStream xpsStream)
    {
        var coverPageXps = new InMemoryRandomAccessStream();
        // Add cover page to XPS content and write to coverPageXps stream
        return coverPageXps;
    }
}

Menonaktifkan UI Faks untuk nomor telepon dari PSA

Dengan dukungan printer faks IPP, sampel ini menunjukkan UI untuk meminta pengguna memasukkan nomor Faks saat mencetak ke printer Faks. Tetapi PSA mungkin ingin menampilkan UI sendiri dengan informasi dan opsi lebih lanjut. Karena membingungkan bagi pengguna jika ada dua UI untuk faks, sampel ini mengilustrasikan opsi bagi PSA untuk menonaktifkan UI sistem saat mereka ingin menampilkan UI Faks mereka.

Sampel berikut menunjukkan penggunaan API.

public sealed class PrintSupportWorkflowBackgroundTask : IBackgroundTask
{

    private void OnJobStarting(PrintWorkflowJobBackgroundSession sender, PrintWorkflowJobStartingEventArgs args)
    {
        using (args.GetDeferral())
        {
            // If the job is printing to an Ipp fax printer,
            // check whether PSA has a custom UI and disable system UI for getting the fax number.
            if (args.IsIPPFaxOutPrinter)
            {
                if (this.HasCustomUIForFax(args.Printer))
                {
                    args.SkipSystemFaxUI = true;
                }
            }
        }
    }

    bool HasCustomUIForFax(IppPrintDevice device)
    {
        bool hasCustomUIForFax = false;
        // Check if the PSA does custom UI for the given fax printer.
        return hasCustomUIForFax;
    }  
}

Komentar

Sampel dalam artikel ini dibangun di atas sampel API PSA v1 dan v2 dalam panduan desain aplikasi dukungan Print dengan asumsi bahwa pengembang terbiasa dengan alur kerja API PSA.

Artikel ini berisi ekstensi untuk API Aplikasi Dukungan Cetak publik yang sudah ada yang dijelaskan dalam panduan desain Aplikasi Dukungan Cetak dan Windows.Graphics.Printing.PrintSupport Namespace. API PSA memungkinkan produsen printer untuk mengembangkan aplikasi UWP yang dapat meningkatkan pengalaman cetak pengguna Windows saat menggunakan Driver Kelas IPP Microsoft bawaan, tanpa perlu mengembangkan driver kustom.

Komponen pencetakan berkomunikasi dengan aplikasi PSA melalui broker PSA.

DisableIppCompressionForJob

Akhir paket layanan untuk driver printer pihak ketiga pada Windows

IsIppCompressionEnabled

IsIPPFaxOutPrinter

IppPrintDevice

MasalahPekerjaanTerdeteksi

PrintSupportIppKomunikasiKonfigurasi

PrintSupportPrintDeviceCapabilitiesChangedEventArgs

SesiLatarBelakangPekerjaanAlurCetak

PrintWorkflowJobIssueDetectedEventArgs

PrintWorkflowJobStartingEventArgs

PrintWorkflowPdlConversionType

SkipSystemErrorToast

Windows.Graphics.Printing.PrintSupport