Coder Social home page Coder Social logo

microsoft / print-oem-samples Goto Github PK

View Code? Open in Web Editor NEW
10.0 19.0 16.0 186 KB

Shows OEM print partners how to use the Print Workflow feature and migrate their existing Windows Store Device Apps (WSDAs) code to the Universal Windows Platform.

License: MIT License

C# 27.89% C++ 72.11%

print-oem-samples's Introduction

Writing print workflow apps and migrating WSDAs to UWP

This sample shows OEM print partners how to use the Print Workflow feature and migrate their existing Windows Store Device Apps (WSDAs) code to the Universal Windows Platform.

About

This is a sample primarily for OEM printer partners to show the combined implementation of both a Print Workflow app and a WSDA. Both are invoked by the OnActivated() method when a user opts to print something to a printer that has been associated with the app.

The Workflow background task uses the XPS Object Model Windows Runtime component to create a PrintWorkflowXpsReceiver implementation, called on a different thread to the app. The generator receives the document object model parts, and the app uses the XPS Object Model to add watermark text and a logo image before sending it to the printer.

The UI foreground task cannot change the XPS data; this must be done by the background task. Therefore, any parameters gathered by the UI are saved in local storage for use by the background task, which then makes the changes. The UI does not exit the OnXpsDataAvailable() function until the required data has been collected.

The main processing is done in the associated background task, and this sample demonstrates how to ensure that the application does not suspend after the UI is dismissed by the Print Workflow Broker user service if there are still background tasks to process. The main application code in the App.xaml.cs file will call a public static method in the background task class to ensure that all background tasks have exited during the Suspending handler, which will allot up to 30 minutes to complete processing.

The PrinterContextNativeRuntimeComponent Windows Runtime Component, initialized through the PrintHelperClass constructor, is of particular importance in the migration of existing Windows 8.1 WSDAs. It gives the Windows Runtime code access to the Printer Extension COM model used in 8.1. It can be initialized with either the traditional WSDA Printer Extension Context or with the new IPrinterExtensionContextNative interface provided in Print Workflow activation contexts.

The IPrinterExtensionContextNative interface has the same functionality as the 8.1 IPrinterExtensionContext interface except for the IPrintSchemaTicket print ticket, because that is available as a first-class WinRT object in the Print Workflow activation scenario.

Test this sample

The following steps will explain how to test this sample app in its intended use cases.

Create a local printing port for testing purposes

You may wish to create a "local port" printer before running the sample. Use a none-production system for this, because you will need to turn on test signing:

Bcdedit.exe -set TESTSIGNING ON

See The TESTSIGNING Boot Configuration Option for more information.

To create a local port, do the following.  

  1. Press Win + R to bring up the Run dialog, and type Control Printers, or %systemroot%\System32\control.exe /name Microsoft.Printers
  2. Select Add a printer
  3. Select The printer is not listed
  4. Select the last item: Add a local printer…
  5. Create a new port. For example: "WorkflowPrinterPort". Select Local and Name your Port
  6. Select Microsoft Enterprise Cloud Print Class Driver
  7. Name the printer. For example: "WorkflowPrinter"
  8. Configure the Workflow policy settings: open a PowerShell window and run the command for the new printer: Set-Printer [-WorkflowPolicy {Uninitialized | Disabled | Enabled}]. For example: Set-Printer WorkflowPrinter -WorkflowPolicy Enabled

You can optionally select the Keep Printed Documents option in the Control Panel Printer Properties.

If you created a local printer port as detailed in the section above, then one way to use this is to open the Device Manager and look at the Details tab in the Properties pane for your printer and set the Property dropdown to Hardware Ids.

At this point you have a printer that writes XPS data to your Documents folder. The name of the output file will match the port name.

Associate the sample app with your printer

To associate the application with the printer, modify the included sample Device Metadata file, Example-WorkflowPrinterPort.devicemetadata-ms, using the Device Metadata Wizard which you can obtain from the Devices and Printers Metadata Authoring Wizard guide. Modify the file to match your printer and import the Package.appxmanifest file to get the app information.

Finally, build and run the sample application, which will install it on your system. You will then be able to test it with real-world scenarios - for example: running Notepad.exe, printing and selecting your printer, then interacting with this application when it is launched.

Related samples

Print settings and print notifications

Printing

System requirements


Client: Windows 10 build 16288 or higher

Build the sample

  1. It is recommended that, in PrintWorkflowXpsReceiver.cpp at the line below, you replace Symbols.ttf with a Unicode font such as ARIALUNI.TTF and also add that font to the Assets folder LPCWSTR fontFileName = L"Assets\Symbols.ttf";
  2. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with the sample you want to build.
  3. Start Microsoft Visual Studio 2017 and select File > Open > Project/Solution.
  4. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the subfolder for this specific sample, then double-click the Visual Studio Solution (.sln) file.
  5. Press Ctrl+Shift+B, or select Build > Build Solution.

Please note that you need to install the Windows SDK version 16288 "Fall Creators Update" or later to build the sample.

Run the sample

To install and run the app, press F5 or use Debug > Start Debugging. To run the app without debugging, press Ctrl+F5 or use Debug > Start Without Debugging.

To debug the application when it is launched through Modern Print Dialog "More settings.." activation, or in the Print Workflow activation, from the Debug menu on Visual Studio 2017 or higher, choose Other Debug Targets > Debug Installed App Package, select Local Machine in the dropdown at the top, and choose the WorkflowAndWSDACombinedSample. Check the Do not launch, but debug my code when it starts and Stop at first statement checkboxes.

print-oem-samples's People

Contributors

ganeshcoep avatar microsoft-github-policy-service[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

print-oem-samples's Issues

IPrinterQueue::SendBidiQuery method may cause Access Violation

Problem Description

For example, when calling the SendInkLevelQuery method below, PrinterContextNativeRuntimeComponent.dll causes an Access Violatuon exception. Please confirm this issue.
https://github.com/microsoft/print-oem-samples/blob/master/PrinterContextNativeRuntimeComponent/PrintHelper.cpp#L132-L136

Investigation / Cause of Problem

You will be able to observe the AV at callstack below. The issue was happened in IUnknown::Release method of IPrintQueue object, because the reference counter has alredy been zero when Release was invoked.

PrinterContextNativeRuntimeComponent.dll!Microsoft::WRL::ComPtr::InternalRelease() line 176 C++
PrinterContextNativeRuntimeComponent.dll!Microsoft::WRL::ComPtr::~ComPtr() line 232 C++
PrinterContextNativeRuntimeComponent.dll!PrinterContextNativeRuntimeComponent::Printing::PrinterExtension::PrinterQueueEventHelperEventArgs::~PrinterQueueEventHelperEventArgs() C++
PrinterContextNativeRuntimeComponent.dll!PrinterContextNativeRuntimeComponent::Printing::PrinterExtension::PrinterQueueEventHelperEventArgs::[Platform::Object]::__abi_Release() C++
PrinterContextNativeRuntimeComponent.dll!__abi_winrt_ptr_dtor(const volatile Platform::Object ^ const __objArg) line 400 C++
PrinterContextNativeRuntimeComponent.dll!PrinterContextNativeRuntimeComponent::Printing::PrinterExtension::PrinterQueueEventHelperCallback::OnBidiResponseReceived(wchar_t * bstrResponse, HRESULT hrStatus) line 59 C++
PrinterContextNativeRuntimeComponent.dll!PrinterContextNativeRuntimeComponent::Printing::PrinterExtension::PrinterQueueEventHelperCallback::Invoke(long dispIdMember, const _GUID & riid, unsigned long lcid, unsigned short wFlags, tagDISPPARAMS * pDispParams, tagVARIANT * pVarResult, tagEXCEPINFO * pExcepInfo, unsigned int * puArgErr) line 128 C++
oleaut32.dll!00007fffe9c3aba4() unknown
oleaut32.dll!00007fffe9c39d50() unknown
rpcrt4.dll!00007fffe94942fb() unknown
combase.dll!00007fffe8bf99f2() unknown
oleaut32.dll!00007fffe9bb3410() unknown
combase.dll!00007fffe8bee1a3() unknown
combase.dll!00007fffe8bedf94() unknown
combase.dll!00007fffe8bfd246() unknown
combase.dll!00007fffe8b9a3a5() unknown
combase.dll!00007fffe8bfceab() unknown
combase.dll!00007fffe8bc6ee0() unknown
combase.dll!00007fffe8bc67c1() unknown
combase.dll!00007fffe8bcf6cd() unknown
combase.dll!00007fffe8bce0dd() unknown
combase.dll!00007fffe8bcfebe() unknown
combase.dll!00007fffe8bcf896() unknown
Windows.UI.dll!00007fffdb6c509c() unknown
Windows.UI.dll!00007fffdb6c4edb() unknown
Windows.UI.Xaml.dll!00007fffda7c4f00() unknown
Windows.UI.Xaml.dll!00007fffda7c4e9f() unknown
twinapi.appcore.dll!00007fffe4964c2a() unknown
twinapi.appcore.dll!00007fffe4937a66() unknown
SHCore.dll!00007fffe95dc315() unknown
kernel32.dll!00007fffe89c7974() unknown
ntdll.dll!00007fffea2da271() unknown

Value Name Type
◢ temp 0x000001cc5dae1150 {...} IPrinterQueue *
◢ IDispatch {...} IDispatch
◢ IUnknown {...} IUnknown

__vfptr 0x0000000000000000 {???, ???, ???} void * *

Workaround

To avoild the AV, I added m_printerQueue->AddRef() methodimmediately after the Attach in the PrinterQueueEventHelperEventArgs.

PrinterQueueEventHelperEventArgs::PrinterQueueEventHelperEventArgs(Object^ printerQueue, String^ str, int hresult)
{
if (printerQueue == nullptr)
{
throw ref new InvalidArgumentException();
}
m_printerQueueEventHR = hresult;
IPrinterQueue* qtmp = (IPrinterQueue*)(void*)printerQueue;
m_printerQueue.Attach(qtmp);
m_printerQueueEventResponse = str;

            m_printerQueueEventHR = hresult;
            IPrinterQueue* qtmp = (IPrinterQueue*)(void*)printerQueue;
            m_printerQueue.Attach(qtmp);
            m_printerQueue->AddRef(); // Workaround
            m_printerQueueEventResponse = str;

XPS print job does not apply Page-level print ticket properties

We implemented PWA based on this project but had a concern with the XPS print job generation. I created a MS Word document with different orientations and paper sizes and attempted to print it using the XpsOMRuntimeComponent project. It printed the job with all pages having the same orientation and paper size. We found changes were necessary in the PrintWorkflowXpsReceiver.cpp AddPage() method to properly apply the different orientations and paper sizes in the document.

After getting the page and dimensions, please get the print ticket by adding these lines:

// Get the print ticket resource
ComPtr<IXpsOMPrintTicketResource> xpsPrintTicketResource;
RETURN_HR_IF_FAILED(xpsOMPageReference->GetPrintTicketResource(&xpsPrintTicketResource));

Then modify the package writer AddPage() call to provide the print ticket resource:

// Finished modifying, so add page to package
RETURN_HR_IF_FAILED(_xpsOMPackageWriter->AddPage(xpsOMPage.Get(), &pageDimensions, nullptr, nullptr, xpsPrintTicketResource.Get(), nullptr));

During notepad print I got

an attempt was made to reference a token that does not exist error.
Event viewer does not show anything what would be the cause?

WorkflowPrintTicket modifications

This is a great example for the new Print Workflow concept which shows how to modify the print content by adding a watermark and a logo. The article which introduces this sample mentions the ability to also modify the print ticket. Documentation for the WorkflowPrintTicket class indicates that it makes changing print ticket values easily. Although I can use the GetParameterInitializer(string, string) method to retrieve a value that I need to change, it seems that the PrintTicketValue class does not have methods to change the values. Including such an example to update the PrintTicket would be very helpful.

UPDATE:
I found the resolution to my question in lines 163 and 164 of WFBackgroundTasks/WfBackgroundTask.cs.

// Send the print ticket to get the Target
PrintWorkflowTarget target = printTaskSubmittedArgs.GetTarget(null);

I suggest that the comment could be updated to:

// Send an updated print ticket when getting the target to change the job ticket details
PrintWorkflowTarget target = printTaskSubmittedArgs.GetTarget(null);

Your project file doesn't list 'win10' as a "RuntimeIdentifier".

hi
i am trying to build and test the project , but i got the error below.

Severity Code Description Project File Line Suppression State
Error Your project file doesn't list 'win10' as a "RuntimeIdentifier". You should add 'win10' to the "RuntimeIdentifiers" property in your project file and then re-run NuGet restore. WorkflowAndWSDACombinedSample

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.