Создание пользовательского рабочего процесса печати
Создание пользовательских рабочих процессов печати с помощью приложения рабочего процесса печати.
Обзор
Приложения рабочих процессов печати — это приложения UWP, расширяющие функциональные возможности приложений устройств Microsoft Store (WSDAs), поэтому вам будет полезно ознакомиться с WSDAs, прежде чем идти дальше.
Так же, как и в случае WSDAs, когда пользователь исходного приложения выбирает печать и переходит через диалоговое окно печати, система проверяет, связано ли приложение рабочего процесса с этим принтером. Если это так, приложение рабочего процесса печати запускается (в первую очередь в качестве фоновой задачи; подробнее об этом ниже). Приложение рабочего процесса может изменить запрос печати (XML-документ, который настраивает параметры устройства принтера для текущей задачи печати) и фактическое содержимое XPS для печати. Кроме того, он может предоставить эту функцию пользователю, запустив пользовательский интерфейс в середине процесса. После выполнения работы он передает содержимое печати и печатает билет на водителя.
Поскольку он включает фоновые и передние компоненты, а также поскольку он функционально связан с другими приложениями, приложение рабочего процесса печати может быть более сложным для реализации, чем другие категории приложений UWP. Рекомендуется проверить пример приложения рабочего процесса при чтении этого руководства, чтобы лучше понять, как можно реализовать различные функции. Некоторые функции, такие как различные проверки ошибок и управление пользовательским интерфейсом, отсутствуют в этом руководстве для простоты.
Начало работы
Приложение рабочего процесса должно указать точку входа в систему печати, чтобы ее можно было запустить в соответствующее время. Это делается путем вставки следующего объявления в Application/Extensions
элемент файла package.appxmanifest проекта UWP.
<uap:Extension Category="windows.printWorkflowBackgroundTask"
EntryPoint="WFBackgroundTasks.WfBackgroundTask" />
Внимание
Существует множество сценариев, в которых настройка печати не требует ввода пользователем. По этой причине приложения рабочего процесса печати выполняются в качестве фоновых задач по умолчанию.
Если приложение рабочего процесса связано с исходным приложением, которое запустило задание печати (см. более поздний раздел инструкций по этому вопросу), система печати проверяет файлы манифеста для точки входа фоновой задачи.
Фоновая работа с билетом на печать
Первое, что делает система печати с приложением рабочего процесса, активирует свою фоновую задачу (в данном случае WfBackgroundTask
класс в WFBackgroundTasks
пространстве имен). В методе фоновой задачи необходимо привести сведения о триггере задачи Run
в качестве экземпляра PrintWorkflowTriggerDetails . Это обеспечит специальные функциональные возможности фоновой задачи рабочего процесса печати. Он предоставляет свойство PrintWorkflowSession, которое является экземпляром PrintWorkFlowBackgroundSession. Классы сеансов рабочего процесса печати — как фон, так и разновидности переднего плана — будут управлять последовательными шагами приложения рабочего процесса печати.
Затем зарегистрируйте методы обработчика для двух событий, которые будет вызывать этот класс сеанса. Эти методы будут определены позже.
public void Run(IBackgroundTaskInstance taskInstance) {
// Take out a deferral here and complete once all the callbacks are done
runDeferral = taskInstance.GetDeferral();
// Associate a cancellation handler with the background task.
taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
// cast the task's trigger details as PrintWorkflowTriggerDetails
PrintWorkflowTriggerDetails workflowTriggerDetails = taskInstance.TriggerDetails as PrintWorkflowTriggerDetails;
// Get the session manager, which is unique to this print job
PrintWorkflowBackgroundSession sessionManager = workflowTriggerDetails.PrintWorkflowSession;
// add the event handler callback routines
sessionManager.SetupRequested += OnSetupRequested;
sessionManager.Submitted += OnXpsOMPrintSubmitted;
// Allow the event source to start
// This call blocks until all of the workflow callbacks complete
sessionManager.Start();
}
Start
При вызове метода диспетчер сеансов сначала вызовет событие SetupRequested. Это событие предоставляет общие сведения о задаче печати, а также билет на печать. На этом этапе билет на печать можно изменить в фоновом режиме.
private void OnSetupRequested(PrintWorkflowBackgroundSession sessionManager, PrintWorkflowBackgroundSetupRequestedEventArgs printTaskSetupArgs) {
// Take out a deferral here and complete once all the callbacks are done
Deferral setupRequestedDeferral = printTaskSetupArgs.GetDeferral();
// Get general information about the source application, print job title, and session ID
string sourceApplicationName = printTaskSetupArgs.Configuration.SourceAppDisplayName;
string jobTitle = printTaskSetupArgs.Configuration.JobTitle;
string sessionId = printTaskSetupArgs.Configuration.SessionId;
// edit the print ticket
WorkflowPrintTicket printTicket = printTaskSetupArgs.GetUserPrintTicketAsync();
// ...
Важно отметить, что в процессе установкиRequested приложение определяет, следует ли запускать компонент переднего плана. Это может зависеть от параметра, ранее сохраненного в локальном хранилище, или события, произошедшие во время редактирования билета на печать, или это может быть статический параметр конкретного приложения.
// ...
if (UIrequested) {
printTaskSetupArgs.SetRequiresUI();
// Any data that is to be passed to the foreground task must be stored the app's local storage.
// It should be prefixed with the sourceApplicationName string and the SessionId string, so that
// it can be identified as pertaining to this workflow app session.
}
// Complete the deferral taken out at the start of OnSetupRequested
setupRequestedDeferral.Complete();
Выполнение переднего плана работы с заданием печати (необязательно)
Если был вызван метод SetRequiresUI, система печати изучит файл манифеста для точки входа в приложение переднего плана. Элемент Application/Extensions
файла package.appxmanifest должен иметь следующие строки. Замените значение EntryPoint
именем приложения переднего плана.
<uap:Extension Category="windows.printWorkflowForegroundTask"
EntryPoint="MyWorkFlowForegroundApp.App" />
Затем система печати вызывает метод OnActivated для заданной точки входа приложения. В методе OnActivated файла App.xaml.cs приложение рабочего процесса должно проверить тип активации, чтобы убедиться, что это активация рабочего процесса. Если это так, приложение рабочего процесса может привести аргументы активации к объекту PrintWorkflowUIActivatedEventArgs, который предоставляет объект PrintWorkflowForegroundSession в качестве свойства. Этот объект, как и его фоновый аналог в предыдущем разделе, содержит события, создаваемые системой печати, и вы можете назначить обработчики этим объектам. В этом случае функции обработки событий будут реализованы в отдельном классе WorkflowPage
.
Во-первых , в файле App.xaml.cs :
protected override void OnActivated(IActivatedEventArgs args){
if (args.Kind == ActivationKind.PrintWorkflowForegroundTask) {
// the app should instantiate a new UI view so that it can properly handle the case when
// several print jobs are active at the same time.
Frame rootFrame = new Frame();
if (null == Window.Current.Content)
{
rootFrame.Navigate(typeof(WorkflowPage));
Window.Current.Content = rootFrame;
}
// Get the main page
WorkflowPage workflowPage = (WorkflowPage)rootFrame.Content;
// Make sure the page knows it's handling a foreground task activation
workflowPage.LaunchType = WorkflowPage.WorkflowPageLaunchType.ForegroundTask;
// Get the activation arguments
PrintWorkflowUIActivatedEventArgs printTaskUIEventArgs = args as PrintWorkflowUIActivatedEventArgs;
// Get the session manager
PrintWorkflowForegroundSession taskSessionManager = printTaskUIEventArgs.PrintWorkflowSession;
// Add the callback handlers - these methods are in the workflowPage class
taskSessionManager.SetupRequested += workflowPage.OnSetupRequested;
taskSessionManager.XpsDataAvailable += workflowPage.OnXpsDataAvailable;
// start raising the print workflow events
taskSessionManager.Start();
}
}
После завершения работы обработчиков событий пользовательского интерфейса и метода OnActivated система печати запустит событие SetupRequested для обработки пользовательского интерфейса. Это событие предоставляет те же данные, что предоставлено событие настройки фоновой задачи, включая сведения о задании печати и документ о печати билета, но без возможности запрашивать запуск дополнительного пользовательского интерфейса. В файле WorkflowPage.xaml.cs:
internal void OnSetupRequested(PrintWorkflowForegroundSession sessionManager, PrintWorkflowForegroundSetupRequestedEventArgs printTaskSetupArgs) {
// If anything asynchronous is going to be done, you need to take out a deferral here,
// since otherwise the next callback happens once this one exits, which may be premature
Deferral setupRequestedDeferral = printTaskSetupArgs.GetDeferral();
// Get information about the source application, print job title, and session ID
string sourceApplicationName = printTaskSetupArgs.Configuration.SourceAppDisplayName;
string jobTitle = printTaskSetupArgs.Configuration.JobTitle;
string sessionId = printTaskSetupArgs.Configuration.SessionId;
// the following string should be used when storing data that pertains to this workflow session
// (such as user input data that is meant to change the print content later on)
string localStorageVariablePrefix = string.Format("{0}::{1}::", sourceApplicationName, sessionID);
try
{
// receive and store user input
// ...
}
catch (Exception ex)
{
string errorMessage = ex.Message;
Debug.WriteLine(errorMessage);
}
finally
{
// Complete the deferral taken out at the start of OnSetupRequested
setupRequestedDeferral.Complete();
}
}
Затем система печати вызовет событие XpsDataAvailable для пользовательского интерфейса. В обработчике этого события приложение рабочего процесса может получить доступ ко всем данным, доступным для события установки, и может дополнительно считывать данные XPS напрямую как поток необработанных байтов, так и как объектную модель. Доступ к данным XPS позволяет пользовательскому интерфейсу предоставлять службы предварительной версии печати и предоставлять пользователю дополнительные сведения об операциях, выполняемых приложением рабочего процесса для данных.
В рамках этого обработчика событий приложение рабочего процесса должно получить объект отсрочки, если он продолжит взаимодействовать с пользователем. Без отсрочки система печати будет рассматривать задачу пользовательского интерфейса после выхода обработчика событий XpsDataAvailable или при вызове асинхронного метода. Когда приложение собрало все необходимые сведения из взаимодействия пользователя с пользовательским интерфейсом, оно должно завершить отсрочку, чтобы затем система печати двигалась вперед.
internal async void OnXpsDataAvailable(PrintWorkflowForegroundSession sessionManager, PrintWorkflowXpsDataAvailableEventArgs printTaskXpsAvailableEventArgs)
{
// Take out a deferral
Deferral xpsDataAvailableDeferral = printTaskXpsAvailableEventArgs.GetDeferral();
SpoolStreamContent xpsStream = printTaskXpsAvailableEventArgs.Operation.XpsContent.GetSourceSpoolDataAsStreamContent();
IInputStream inputStream = xpsStream.GetInputSpoolStream();
using (var inputReader = new Windows.Storage.Streams.DataReader(inputStream))
{
// Read the XPS data from input stream
byte[] xpsData = new byte[inputReader.UnconsumedBufferLength];
while (inputReader.UnconsumedBufferLength > 0)
{
inputReader.ReadBytes(xpsData);
// Do something with the XPS data, e.g. preview
// ...
}
}
// Complete the deferral taken out at the start of this method
xpsDataAvailableDeferral.Complete();
}
Кроме того, экземпляр PrintWorkflowSubmittedOperation, предоставляемый args событиями, предоставляет возможность отменить задание печати или указать, что задание успешно выполнено, но выходные задания печати не потребуются. Это делается путем вызова метода Complete со значением PrintWorkflowSubmittedStatus.
Примечание.
Если приложение рабочего процесса отменяет задание печати, настоятельно рекомендуется предоставить всплывающее уведомление о том, почему задание было отменено.
Выполните окончательную фоновую работу с содержимым печати
После завершения отсрочки пользовательского интерфейса в событии PrintTaskXpsDataAvailable (или при обходе шага пользовательского интерфейса) система печати запустит событие "Отправлено" для фоновой задачи. В обработчике этого события приложение рабочего процесса может получить доступ ко всем одинаковым данным, предоставляемым событием XpsDataAvailable . Однако, в отличие от любого из предыдущих событий, Отправленный также предоставляет доступ на запись к содержимому задания окончательной печати через экземпляр PrintWorkflowTarget.
Объект, используемый для подкаки данных для окончательной печати, зависит от того, осуществляется ли исходный поток как необработанный поток байтов или как объектная модель XPS. Когда приложение рабочего процесса обращается к исходным данным через поток байтов, выходной байтовый поток предоставляется для записи окончательных данных задания. Когда приложение рабочего процесса обращается к исходным данным через объектную модель, средство записи документов предоставляется для записи объектов в выходное задание. В любом случае приложение рабочего процесса должно считывать все исходные данные, изменять все необходимые данные и записывать измененные данные в целевой объект вывода.
Когда фоновая задача завершит запись данных, она должна вызвать Complete для соответствующего объекта PrintWorkflowSubmittedOperation. После завершения этого шага и выхода обработчика событий "Отправленный " сеанс рабочего процесса закрывается, а пользователь может отслеживать состояние окончательного задания печати с помощью стандартных диалоговых окон печати.
Заключительные действия
Регистрация приложения рабочего процесса печати на принтере
Приложение рабочего процесса связано с принтером, используя тот же тип отправки файла метаданных, что и для WSD. На самом деле одно приложение UWP может выступать как в качестве приложения рабочего процесса, так и WSDA, предоставляющего функциональные возможности параметров задачи печати. Выполните соответствующие действия WSDA по созданию ассоциации метаданных.
Разница заключается в том, что хотя WSDA автоматически активируются для пользователя (приложение всегда запускается при печати этого пользователя на связанном устройстве), приложения рабочих процессов не являются. У них есть отдельная политика, которая должна быть задана.
Настройка политики приложения рабочего процесса
Политика приложения рабочего процесса устанавливается командами PowerShell на устройстве, которое предназначено для запуска приложения рабочего процесса. Команды Set-Printer, Add-Printer (существующий порт) и Add-Printer (новый порт WSD) будут изменены, чтобы разрешить устанавливать политики рабочих процессов.
Disabled
: приложения рабочего процесса не будут активированы.Uninitialized
: приложения рабочего процесса будут активированы, если DCA рабочего процесса установлен в системе. Если приложение не установлено, печать по-прежнему продолжится.Enabled
: контракт рабочего процесса будет активирован, если DCA рабочего процесса установлен в системе. Если приложение не установлено, печать завершится ошибкой.
Следующая команда делает приложение рабочего процесса обязательным на указанном принтере.
Set-Printer –Name "Microsoft XPS Document Writer" -WorkflowPolicy Enabled
Локальный пользователь может запустить эту политику на локальном принтере или для корпоративной реализации администратор принтера может запустить эту политику на сервере печати. Затем политика будет синхронизирована со всеми клиентскими подключениями. Администратор принтера может использовать эту политику всякий раз, когда добавляется новый принтер.