◆ CreatorsUpdate した PC で AddJob メソッドで印刷できない
◆ それ以前の Windows10 や 7/8.1 はできる
◆ 複数の PC で確認済み
◆ XPS Document Writer など特殊なプリンタの場合は印刷可能
◆ 実際のプリンタや PrimoPDF みたいなファイルへ印刷するツールで印刷できない 

WPF で XPS の印刷

WPF で XPS ファイルを印刷するサンプルです

<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="400">
<StackPanel VerticalAlignment="Center">
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="200"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Margin" Value="20"/>
</Style>
</StackPanel.Resources>
<Button Click="printByAddJob">printByAddJob</Button>
<Button Click="printByPrintDialog">printByPrintDialog</Button>
<Button Click="printByDocumentWriter">printByDocumentWriter</Button>
</StackPanel>
</Window>
using System.Printing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Xps.Packaging;

namespace WpfApp1
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
}

private void printByAddJob(object sender, RoutedEventArgs e)
{
var print_dialog = new PrintDialog();
print_dialog.ShowDialog();

var print_queue = print_dialog.PrintQueue;
var print_ticket = print_dialog.PrintTicket;

print_queue.AddJob("job-name", @"C:\Data\Book1.xps", false, print_ticket.Clone());
}

private void printByPrintDialog(object sender, RoutedEventArgs e)
{
var print_dialog = new PrintDialog();
print_dialog.ShowDialog();

using (var xps_document = new XpsDocument(@"C:\Data\Book1.xps", System.IO.FileAccess.Read))
{
var document_sequence = xps_document.GetFixedDocumentSequence();
print_dialog.PrintDocument(document_sequence.DocumentPaginator, "job-name");
}
}

private void printByDocumentWriter(object sender, RoutedEventArgs e)
{
var print_dialog = new PrintDialog();
print_dialog.ShowDialog();

var print_queue = print_dialog.PrintQueue;
var print_ticket = print_dialog.PrintTicket;

using (var xps_document = new XpsDocument(@"C:\Data\Book1.xps", System.IO.FileAccess.Read))
{
print_queue.CurrentJobSettings.Description = "job-name";
var writer = PrintQueue.CreateXpsDocumentWriter(print_queue);
var document_sequence = xps_document.GetFixedDocumentSequence();
writer.Write(document_sequence, print_ticket.Clone());
}
}
}
}

ボタンが 3 つで 3 パターンの印刷方法があります

1 つ目の printByAddJob は PrintQueue の AddJob メソッドに XPS ファイルのパスを渡して印刷します
2 つ目の printByPrintDialog は PrintDialog の機能を使って印刷します
3 つ目の printByDocumentWriter は XPS ファイルを読み込んでそのデータを DocumentWriter を使って印刷します

PrintDialog の内部では 3 つ目と同じように DocumentWriter を使って印刷しています
ReferenceSource PrintDialog

Creators Update で印刷できない

これまで (Windows 7 や Windows 8.1 や Windows 10 (TH2 / Anniversary Update)) の OS では全部印刷できました
ですが Creators Update にすると 1 つ目の方法が使えなくなりました


エラーがでるわけでもなく AddJob メソッドが終了しません
無限ループで CPU 使用率が 100% になってるわけでもないです
デバッグモードでステップ実行するとこの次の行がいつまでたっても実行されません
画面としては 操作できない状態がずっと続きます


2 つ目のダイアログの方法は問題なく使えました
3 つ目も中身は同じことなので印刷できます
別の方法を使えば対処できるのでまぁいいのですが Windows 10 のアップデートはろくなことがない気がします
前回の Anniversary Update でも .NET から Excel を操作する場合におかしくなるバグがありましたし


AddJob メソッドはファイルのパスを渡すだけで印刷できる便利なメソッドですが Creators Update 後の Windows 10 にも対応させるとなると ユーザが選択するダイアログありなら 2 つ目の方法を ダイアログなしで印刷するなら 3 つ目の方法を使うようにしておく必要があります

Anniversary Update のときみたいに Windows 側の設定で対処できればいいのですけどね


この現象は Windows 10 より前の OS からアップグレードしてきた PC と Windows TH2 をクリーンインストールしてアップグレードしてきた PC どちらでも起きていたので PC 固有の問題じゃなくて Creators Update した PC 全体に影響あるかと思います
そのわりに情報が全然なくて StackOverflow で見つけた質問も解答なしでした

仮想プリンタでは起きない

最近の Windows では PDF や XPS に印刷するプリンタがデフォルトで入っています

  • Microsoft Print to PDF
  • Microsoft XPS Document Writer

この 2 つ

これらを使う場合は AddJob でも印刷可能です

実際のプリンタが指定されると印刷できません
実際のプリンタでなくても サードパーティの PDF へ出力するツールでも発生しました

紙の無駄遣いはしたくないので 私は Primo PDF というソフトで試しましたが再現されました
最新版は有料ぽいので旧版です
PrimoPDF