Designguide för utskriftsstödprogram v3 API
Den här artikeln innehåller vägledning och exempel för skrivartillverkare och oavhängiga maskinvaruleverantörer som implementerar en v3 Print Support App (PSA) för sina enheter.
Terminologi
Term | Definition |
---|---|
PSA | Utskriftsstödprogram. UWP-app som använder API:et i det här dokumentet. |
IPP | Internet Printing Protocol. Används från en klientenhet för att interagera med skrivaren för att hämta och ange utskriftsinställningar och för att skicka dokumentet som ska skrivas ut. |
Associerad skrivare för utskriftsstöd | Fysisk IPP-skrivare som är länkad till PSA. |
IPP-skrivare | Skrivare som stöder IPP-protokoll. |
PDL | Språk för sidbeskrivning. Formatet där ett dokument skickas till skrivaren. |
Associerad PSA-skrivare | Fysisk IPP-skrivare som är associerad med ett PSA-program. |
Utskriftsenhetens kapabiliteter | XML-dokumentformat för att definiera skrivarfunktioner. |
Utskriftsstödstillägg | PSA-bakgrundsaktivitet som ansvarar för att tillhandahålla utökade funktioner för skrivarbegränsningar. |
Utskriftsstödprogram v3 API
Den här artikeln innehåller v3-tilläggen till det befintliga offentliga API:et för utskriftssupportprogrammet som beskrivs i designguiden för utskriftssupportappen och Windows.Graphics.Printing.PrintSupport Namnområde. PSA-API:et gör det möjligt för skrivartillverkare att utveckla maskinvarusupportappar som kan förbättra en Windows-användares utskriftsupplevelse när de använder Inkorgens Microsoft IPP-klassdrivrutin utan att behöva utveckla en anpassad drivrutin. Utskriftskomponenter kommunicerar med PSA-appen via en PSA-koordinatorprocess.
Mer information finns i följande artiklar:
Ämne | Beskrivning |
---|---|
Designguide för utskriftssupportapp | Innehåller vägledning och exempel för skrivar-OEM:er och IHV:er som implementerar en skrivarsupportapp för sina enheter. |
designguide för Print Support App v4 API | Innehåller vägledning och exempel för skrivar-OEM:er och IHV:er som implementerar en v4 Print Support App (PSA) för sina enheter. |
MSIX-manifestspecifikation för virtuell skrivare med utskriftsstöd | Innehåller MSIX-manifestvägledning och exempel för skrivar-OEM och IHV:er som implementerar en virtual skrivare med utskriftsstöd. |
Skrivarstöd för app-koppling | Innehåller vägledning och exempel för att associera en psa (print support app) med en skrivare. |
De betydande tilläggen till API:et är följande:
IPP-komprimering – PSA v3 API lägger till en funktion för att förbättra IPP-utskrift genom att lägga till en IPP-komprimeringsfunktion i ett utskriftsjobb för IPP-skrivare som stöder den här funktionen. Vissa PSA kan ha anpassad komprimering, vilket innebär att IPP-jobbet har dubbel komprimering som påverkar prestandan. För att minimera detta introducerar PSA v3 API en egenskap IsIppCompressionEnabled och en DisableIppCompressionForJob-funktion (för att inaktivera komprimering för det aktuella jobbet om det behövs) i PrintWorkflowJobStartingEventArgs (PSA v1 API) körningsklass.
IPP-jobbsfelhantering och felmeddelande- – PSA v3 API introducerar en JobIssueDetected-händelse i PrintWorkflowJobBackgroundSession-körningsklassen (PSA v1 API). Händelsen utlöses när PSA upptäcker ett fel/en varning i utskriftsjobbet. PSA ansvarar sedan för att visa felmeddelandet för användaren. När PSA registrerar sig för den här händelsen och anger SkipSystemErrorToast-egenskapen till true i PrintWorkflowJobIssueDetectedEventArgs, uppmanas utskriftssystemet att inte visa popup-brödet för Windows-utskriftssystemet. PSA v3-API:et tillhandahåller också en mekanism för PSA att starta användargränssnittet när användaren interagerar med en avisering.
tidsgränser för anpassad IPP-kommunikation – PSA v3 API tillhandahåller ett API med vilket ett PSA kan åsidosätta IPP-tidsgränserna. Dessutom läggs PrintSupportIppCommunicationConfiguration-körningsklassen till i PrintSupportPrintDeviceCapabilitiesChangedEventArgs för att ändra tidsgränserna för IPP-kommunikation. Dessutom introducerar PSA v3 API en händelse som utlöses när det uppstår ett fel med IPP-kommunikationen. Händelsen introducerades så att IHV kunde undersöka felet och justera tidsgränsvärdena i enlighet med detta.
Support IPPFaxOut – PSA v3 API lägger till en funktion i utskriftssystemet för att stöda IPPFaxOut-skrivare. PSA stöder ett återgivningsfilter för att konvertera XPS till Tiff för att stödja Fax. Eftersom PSA kan komma att manipulera XPS-innehållet innan det konverteras till TIFF, tillhandahåller det XpsToTiff-uppräkningsvärdet i PrintWorkflowPdlConversionType- för att PSA ska kunna få åtkomst till XPS till TIFF-konverteraren. Dessutom tillhandahåller den egenskapen IsIPPFaxOutPrinter till IppPrintDevice-körningsklass så att PSA kan skilja mellan standardskrivaren och IPPFaxOut-skrivarna.
Avaktivera IPP-komprimering
IPP-komprimering visas i följande kodexempel.
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;
}
}
Felhantering av IPP-jobb
Det här exemplet visar hur PSA-appen kan registrera jobbfel, visa toastmeddelanden för jobbfel och starta användargränssnittet när användaren aktiverar dessa meddelanden.
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;
}
}
Ange tidsgräns för IPP-kommunikation
Det här exemplet visar hur du anger tidsgränsen för IPP-kommunikation.
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;
}
}
}
Hantera IPP-kommunikationsfel
Det här exemplet visar hur du hanterar IPP-kommunikationsfel.
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
}
}
}
}
Skriva ut till IPP-faxskrivare i PSA
Det här exemplet visar hur du skriver ut till en IPPFaxOut-skrivare i en 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;
}
}
Inaktivera faxgränssnittet för telefonnummer från PSA
Med stöd för IPP-faxskrivaren visar det här exemplet ett användargränssnitt för att begära att användaren anger faxnumret vid utskrift till faxskrivaren. Men PSA kanske vill visa ett eget användargränssnitt med mer information och alternativ. Eftersom det är förvirrande för användaren om det finns två UIs för fax, visar det här exemplet ett alternativ för ett PSA för att inaktivera systemgränssnittet när de vill visa sitt faxgränssnitt.
Följande exempel visar API-användningen.
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;
}
}
Anmärkningar
Exempel i den här artikeln bygger på exemplen på API:erna PSA v1 och v2 i designguiden för Print-supportappen med antagandet att utvecklaren är bekant med PSA API-arbetsflödet.
Den här artikeln innehåller tilläggen för det befintliga offentliga API:et för utskriftsstödprogram som beskrivs i designguiden för utskriftssupportappen och Windows.Graphics.Printing.PrintSupport Namnområde. PSA-API:et gör det möjligt för skrivartillverkare att utveckla UWP-appar som kan förbättra en utskriftsupplevelse för Windows-användare när de använder Inkorgens Microsoft IPP-klassdrivrutin, utan att behöva utveckla en anpassad drivrutin.
Utskriftskomponenter kommunicerar med PSA-appen genom en PSA broker-process.
Relaterade artiklar
Serviceplan upphör för skrivardrivrutiner från tredje part i Windows
PrintSupportIppCommunicationConfiguration
PrintSupportPrintDeviceCapabilitiesChangedEventArgs
PrintWorkflowJobBackgroundSession
PrintWorkflowJobIssueDetectedEventArgs
PrintWorkflowJobStartingEventArgs