6

I want to create a UWP Printer application to set up a virtual printer that I then can select from windows print dialog following the Print Support App design guide as good as I can.

I expect that at least the "MyCustomPrinter" (defined in Package.appxmanifest further down) shows up in the list when I want to print something, but it doesn't.

missing virtual printer

I have never done this before (driver/psa app) so this is completely new to me and confuses me alot.

My problem is that the printer is just not shown in the device list and the Print Support App design guide might be one of the worst and most confusing documentations I have ever seen.

In any case I can't make heads or tails of it.

So what I did was to create a blank uwp app by selecting the "Blank App (Universal Windows)" in Visual Studio 2022 to create my application.

I would like to share a large part of my code at this point to make sure that I do not withhold any important information from you

Here we go:

App.xaml

<Application
    x:Class="PrintingApp.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PrintingApp">
</Application>

App.xaml.cs

using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Graphics.Printing.PrintSupport;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace PrintingApp
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default <see cref="Application"/> class.
    /// </summary>
    sealed partial class App : Application
    {
        Deferral settingsDeferral;
        protected override void OnActivated(IActivatedEventArgs args)
        {
            if (args.Kind == ActivationKind.PrintSupportSettingsUI)
            {
                // Get the activation arguments
                var settingsEventArgs = args as PrintSupportSettingsActivatedEventArgs;
                PrintSupportSettingsUISession settingsSession = settingsEventArgs.Session;
                // Take deferral
                this.settingsDeferral = settingsEventArgs.GetDeferral();

                // Create root frame
                var rootFrame = new Frame();

                // Choose the page to be shown based upon where the application is being launched from
                switch (settingsSession.LaunchKind)
                {
                    case SettingsLaunchKind.UserDefaultPrintTicket:
                    {
                        // Show settings page when launched for default printer settings
                        rootFrame.Navigate(typeof(DefaultSettingsView), settingsSession);
                    }
                        break;
                    case SettingsLaunchKind.JobPrintTicket:
                    {
                        // Show settings page when launched from printing app
                        rootFrame.Navigate(typeof(MainPage), settingsSession);
                    }
                        break;
                }


                Window.Current.Content = rootFrame;
            }
        }

        internal void ExitSettings()
        {
            settingsDeferral.Complete();
        }
    }
}

Package.appxmanifest

<?xml version="1.0" encoding="utf-8"?>

<Package
    xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
    xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
    xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
    xmlns:uap11="http://schemas.microsoft.com/appx/manifest/uap/windows10/11"
    xmlns:printsupport="http://schemas.microsoft.com/appx/manifest/printsupport/windows10"
    xmlns:printsupport2="http://schemas.microsoft.com/appx/manifest/printsupport/windows10/2"
    xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
    xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"
    IgnorableNamespaces="uap mp desktop4 iot2 printsupport printsupport2 uap11">

  <Identity
    Name="bc0e7b39-aec8-4569-85ad-b42b6da40308"
    Publisher="CN=CrazyEight"
    Version="1.0.0.0" />

  <mp:PhoneIdentity PhoneProductId="bc0e7b39-aec8-4569-85ad-b42b6da40308" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

  <Properties>
    <DisplayName>PrintingApp</DisplayName>
    <PublisherDisplayName>CrazyEight</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>

  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>

  <Resources>
    <Resource Language="x-generate"/>
  </Resources>

  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="PrintingApp.App"
      desktop4:SupportsMultipleInstances="true"
      iot2:SupportsMultipleInstances="true">
      <uap:VisualElements
        DisplayName="PrintingApp"
        Square150x150Logo="Assets\Square150x150Logo.png"
        Square44x44Logo="Assets\Square44x44Logo.png"
        Description="PrintingApp"
        BackgroundColor="transparent">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>

        <Extensions>
            <!--1. Virtueller Drucker-Workflow-->
            <printsupport2:Extension
                Category="windows.printSupportVirtualPrinterWorkflow"
                EntryPoint="PrintingApp.Tasks.PrintSupportWorkflowBackgroundTask"
                uap11:SupportsMultipleInstances="true">
                <printsupport2:PrintSupportVirtualPrinter
                    DisplayName="MyCustomPrinter"
                    PreferredInputFormat="application/postscript"
                    OutputFileTypes="ps,pdf"
                    PdcFile="Config\PRINTERPDC1.xml">
                    <printsupport2:SupportedFormats>
                        <printsupport2:SupportedFormat Type="application/postscript" />
                        <printsupport2:SupportedFormat Type="application/pdf" MaxVersion="1.7" />
                    </printsupport2:SupportedFormats>
                </printsupport2:PrintSupportVirtualPrinter>
            </printsupport2:Extension>

            <!--2. Print-Support-Extension-->
            <printsupport:Extension
                Category="windows.printSupportExtension"
                EntryPoint="PrintingApp.Tasks.PrintSupportExtensionBackgroundTask"
                uap11:SupportsMultipleInstances="true" >
            </printsupport:Extension>

            <!--3. Print-Support-SettingsUI-->
            <printsupport:Extension
                Category="windows.printSupportSettingsUI"
                EntryPoint="PrintingApp.App"
                uap11:SupportsMultipleInstances="true" />

            <!--4. Print-Support-JobUI-->
            <printsupport:Extension
                Category="windows.printSupportJobUI"
                EntryPoint="PrintingApp.Tasks.PrintSupportJobUIBackgroundTask"
                uap11:SupportsMultipleInstances="true" />
        </Extensions>
    </Application>
  </Applications>

  <Capabilities>
    <Capability Name="internetClient" />
  </Capabilities>
</Package>

printerpdc1.xml (Build Action = Content and Copy to Output Directory = Always)

<?xml version="1.0" encoding="UTF-8"?>
<PrintDeviceCapabilities
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:psk="https://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords"
    xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
    xmlns:psf2="https://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2"
    xmlns="https://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2"
    version="2">
    <CapabilitiesChangeID xsi:type="xsd:string">617e6418-6847-4fa1-bec6-3a3668d09f6d</CapabilitiesChangeID>
    <!-- Hier folgen <Feature>- und <Option>-Definitionen -->

    <!-- Required minimal feature: Page Media Size -->
    <Feature name="psk:PageMediaSize">
        <Option name="psk:ISOA4" />
    </Feature>

    <!-- Required minimal feature: Page Orientation -->
    <Feature name="psk:Orientation">
        <Option name="psk:Portrait" />
    </Feature>
</PrintDeviceCapabilities>

PrintSupportWorkflowBackgroundTask

  • other tasks have only taskInstance.GetDeferral().Complete(); implementation in Run method
using Windows.ApplicationModel.Background;
using Windows.Graphics.Printing.PrintSupport;
using Windows.Graphics.Printing.Workflow;

namespace PrintingApp.Tasks
{
    /// <summary>
    /// Background-Task für den virtuellen Drucker-Workflow.
    /// </summary>
    public sealed partial class PrintSupportWorkflowBackgroundTask : IBackgroundTask
    {
        BackgroundTaskDeferral taskDeferral;
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Take Task Deferral            
            taskDeferral = taskInstance.GetDeferral();

            var jobTriggerDetails = taskInstance.TriggerDetails as PrintWorkflowJobTriggerDetails;
            // This registers the virtual printer for the app
            var workflowBackgroundSession = jobTriggerDetails.PrintWorkflowJobSession as PrintWorkflowJobBackgroundSession;
            // Register for events
            workflowBackgroundSession.JobStarting += this.OnJobStarting;
            workflowBackgroundSession.PdlModificationRequested += this.OnPdlModificationRequested;
            // Start Firing events
            workflowBackgroundSession.Start();

            taskDeferral.Complete();
        }

        private void OnPdlModificationRequested(PrintWorkflowJobBackgroundSession sender, PrintWorkflowPdlModificationRequestedEventArgs args)
        {
            // TODO
        }

        private void OnJobStarting(PrintWorkflowJobBackgroundSession session, PrintWorkflowJobStartingEventArgs args)
        {
            using (args.GetDeferral())
            {
                // Call SetSkipSystemRendering to skip conversion for XPS to PDL, so that PSA can directly manipulate the XPS file.
                args.SetSkipSystemRendering();
            }
        }
    }
}

csproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProjectGuid>{BFDA5F9B-D16A-4460-8F23-D55AACBEA9EA}</ProjectGuid>
    <OutputType>AppContainerExe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>PrintingApp</RootNamespace>
    <AssemblyName>PrintingApp</AssemblyName>
    <DefaultLanguage>en-US</DefaultLanguage>
    <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
    <TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.22621.0</TargetPlatformVersion>
    <TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
    <MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
    <AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
    <GenerateAppInstallerFile>False</GenerateAppInstallerFile>
    <PackageCertificateKeyFile>PrintingApp_TemporaryKey.pfx</PackageCertificateKeyFile>
    <AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
    <AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
    <GenerateTestArtifacts>True</GenerateTestArtifacts>
    <AppxBundle>Always</AppxBundle>
    <AppxBundlePlatforms>x64</AppxBundlePlatforms>
    <HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x86\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>x86</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
    <OutputPath>bin\x86\Release\</OutputPath>
    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x86</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\ARM\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>ARM</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
    <OutputPath>bin\ARM\Release\</OutputPath>
    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>ARM</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\ARM64\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>ARM64</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
    <OutputPath>bin\ARM64\Release\</OutputPath>
    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>ARM64</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x64\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
    <OutputPath>bin\x64\Release\</OutputPath>
    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup>
    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
    </Compile>
    <Compile Include="DefaultSettingsView.xaml.cs">
      <DependentUpon>DefaultSettingsView.xaml</DependentUpon>
    </Compile>
    <Compile Include="MainPage.xaml.cs">
      <DependentUpon>MainPage.xaml</DependentUpon>
    </Compile>
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Tasks\PrintSupportExtensionBackgroundTask.cs" />
    <Compile Include="Tasks\PrintSupportJobUIBackgroundTask.cs" />
    <Compile Include="Tasks\PrintSupportSettingsUIBackgroundTask.cs" />
    <Compile Include="Tasks\PrintSupportWorkflowBackgroundTask.cs" />
  </ItemGroup>
  <ItemGroup>
    <AppxManifest Include="Package.appxmanifest">
      <SubType>Designer</SubType>
    </AppxManifest>
  </ItemGroup>
  <ItemGroup>
    <Content Include="Config\PRINTERPDC1.xml">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <Content Include="Properties\Default.rd.xml" />
    <Content Include="Assets\LockScreenLogo.scale-200.png" />
    <Content Include="Assets\SplashScreen.scale-200.png" />
    <Content Include="Assets\Square150x150Logo.scale-200.png" />
    <Content Include="Assets\Square44x44Logo.scale-200.png" />
    <Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
    <Content Include="Assets\StoreLogo.png" />
    <Content Include="Assets\Wide310x150Logo.scale-200.png" />
  </ItemGroup>
  <ItemGroup>
    <ApplicationDefinition Include="App.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </ApplicationDefinition>
    <Page Include="DefaultSettingsView.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Page Include="MainPage.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
      <Version>6.2.14</Version>
    </PackageReference>
  </ItemGroup>
  <ItemGroup>
    <None Include="PrintingApp_TemporaryKey.pfx" />
  </ItemGroup>
  <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
    <VisualStudioVersion>14.0</VisualStudioVersion>
  </PropertyGroup>
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
3
  • Thanks for posting your code. Did the answers help? Somebody asked at MS Q&A, but nothing there yet. Commented Sep 20 at 5:27
  • I face the same problem. What i found was that event viewer shows warnings : "App manifest validation warning: Declared namespace schemas.microsoft.com/appx/manifest/printsupport/windows10/2 is inapplicable, it will be ignored during manifest processing." I think that means it ignores the whole section "printsupport2:Extension" including the background task. Sadly i have no idea why its inapplicable. Commented 2 days ago
  • The event log entries can be found at: Applications and Services Logs → Microsoft → Windows → AppXDeployment-Server → Operational Commented 2 days ago

2 Answers 2

0

In the Package.appxmanifest
Can you try printSupport capability

<Capabilities>
    <Capability Name="internetClient" />
    <DeviceCapability Name="windows.printing.printSupport" />
</Capabilities>
Sign up to request clarification or add additional context in comments.

Comments

-1

Your code is out of date. Review updated instructions at below including new background task.

https://learn.microsoft.com/en-us/windows-hardware/drivers/devapps/print-support-app-v4-design-guide

Note: the package manifest section DisplayName="..."

This is must be a string resource NOT hard coded and correct syntax is DisplayName="ms-resource:PdfPrintDisplayName" without the slashes

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.