4
3

Blazor ServerでPDFをサイレント印刷する方法(無料のWebView2使用)

Posted at

はじめに

お仕事にてClassic aspおよびASP.NETで作成された既存アプリケーションをBlazor Serverに作り替える作業をしています。
ラベルプリンターの印刷があるシステムの改修する段階となり、使用している外部モジュールなどもバージョンアップしました。

ただFreeSpire.PDFのバージョン 10.2.0にしたところ、印刷メソッドが削除されていました。一つ前のバージョン 8.6.0は問題ないため、このバージョンにしています。

小さい文字の印字

ラベルプリンターの印刷なので小さい文字が必要となります。
MSゴシック 6ptの文字を印字すると、Acrobat Readerでは印字した場合は細い線を保ったまま綺麗な文字で印字されるが、FreeSpire.PDFだと細い線が汚く印字される。もちろんその状態でも問題なく読めるので運用上は困ることはない。綺麗な状態を知っていると残念なところである。

image.png

上がAcrobat Readerによる印字、下がFreeSpire.PDFによる印字
ghostscript.netも試してみましたが、FreeSpire.PDFと同じ印字状態でした。

フォントを調整することで、そこそこマシになりました。

本題

Acrobat Readerの代替になるものを考えた時に、Microsoft EdgePDFを表示および印刷が出来ることに気が付きました。

WebView2コントロールを使用して、PDFファイルを印刷するようにしたいと考えました。その際に印刷ダイアログ画面を出さないサイレント印刷を行う。

Acrobat Reader/Adobe Reader をサーバーにインストールし、ネットワーク経由で使用する方法は原則的に禁止されています。
Acrobat Reader/Adobe Reader のサーバー利用について

印刷プログラムの作成

WebView2コントロールはWindows Formsアプリケーション(またはWPF)のコンテキスト内で動作するように設計されています。

印刷プログラムとして「WebView2PdfPrinter.exe」を作成します。

  1. Windows Formsアプリケーション(またはWPF)で、WebView2コントロールを貼り付けます。
  2. コマンドライン引数または設定ファイルで、印刷に必要なパラメーター(最低でもPDFファイルのパス名とプリンター名)を渡します。
  3. LoadイベントでPrintPdfメソッドを呼びます。
  4. ビルドしたexeを実行して、パラメーターのpdfファイルが印刷できることを確認します。
private void frmMain_Load(object sender, EventArgs e)
{
    // コマンドライン引数を取得
    string[] args = Environment.GetCommandLineArgs();
    string pdfPath = args[1];
    string printerName = args[2];
    int count;
    int.TryParse(args[3], out count);
    if (count == 0) count = 1;

    // 印刷処理
    PrintPdf(pdfPath, printerName, count);
}

public void PrintPdf(string pdfPath, string printerName, int count)
{
    webView2.Source = new Uri(pdfPath);
    webView2.NavigationCompleted += async (sender, e) =>
    {
        if (e.IsSuccess)
        {
           CoreWebView2PrintSettings printSettings = webView2.CoreWebView2.Environment.CreatePrintSettings();
           printSettings.PrinterName = printerName;
           printSettings.Copies = count;

           var printStatus = await webView2.CoreWebView2.PrintAsync(printSettings);
        }
    }
}

PrintSettingsクラス

印刷に必要なパラメーターとして、PrintSettingsクラスをセットして渡します。
パラメーター数が多いのでコマンドラインで渡す場合は最小限とし、多くのパラメーターを活かしたいなら設定ファイルで読み込む方式にします。

DLL化の検討

普通にVisual Studioのテンプレートでクラスライブラリーを作成しても、System.Windows.Forms名前空間を使用できないんですが、下記の方法でDLL化することが出来ました。

上記サイトに従い、csprojファイルをテキストエディタで開いて下記を追加します。

<UseWindowsForms>true</UseWindowsForms>

しかし、Blazor Serverで作成したDLLを参照して使用しようとすると、Blazor Server側にもUseWindowsFormsの設定とNuGetでWebView2の参照が必要になってしまう。
それは嫌だなと思ってやめました。

印刷プログラムの呼び出し

Blazor Serverで印刷プログラムを呼び出して使用します。

今回は例として、「C:¥Tool¥WebView2PdfPrinter」フォルダに、WebView2PdfPrinter.exe と関連するWebView2などのモジュールを置きます。

Blazor Serverのサンプルアプリケーションで、カウントボタンをクリックしたら印刷されるようにします。
PDFファイルは「LBL00001.pdf」、プリンター名は「EPSON PX-501A」、部数は「1」を指定します。

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;

        Task.Run(() => Print());
    }

    private void Print()
    {
        string directory = @"C:\Tool\WebView2PdfPrinter\";
        string toolFilepath = Path.Combine(directory, "WebView2PdfPrinter.exe");
        string pdfPath = Path.Combine(directory, "LBL00001.pdf");
        string printerName = "EPSON PX-501A";
        int count = 1;

        var processStartInfo = new ProcessStartInfo
        {
            FileName = toolFilepath,
            Arguments = $"{pdfPath} \"{printerName}\" {count}",
            WindowStyle = ProcessWindowStyle.Hidden,
            CreateNoWindow = true,
            RedirectStandardOutput = true,
            UseShellExecute = false,
        };

        using (var process = Process.Start(processStartInfo)) {
            // タイムアウト5秒を設定してプロセスの完了を待つ
            if (!process.WaitForExit(5000))
            {
                // プロセスを強制終了する
                process.Kill();
            }
        }
    }
}

PDFのサイレント印刷

IIS用に「C:\inetpub\wwwroot\print」フォルダに発行し、Webブラウザで「localhost/print」してBlazor Serverのサンプルアプリケーションを動かします。
カウントボタンをクリックするとサイレント印刷されるようになります。

配置の注意点

当初は印刷プログラムを「C:¥Tool¥Printer」フォルダではなく、「C:\inetpub\wwwroot\Printer\WebView2PdfPrinter」フォルダに配置したのですが、ここに配置すると権限の問題なのか印刷が出来なくなります。
調査のために色々試してみたのですがPDF表示がそもそも出来なかったです。

inetpubフォルダ以外なら印刷できるので、とりあえずヨシとしました。

最後に

PDFの編集するライブラリーは多くありますが、印刷までサポートしているのはSpire.PDFなど少ししかありません。ただ無料版のFreeSpire.PDFのバージョン 10.2.0にしたところ、印刷メソッドが削除されていました。
PDFを印刷するには画像に変換する必要があるからハードルが高いようです。

WebView2を使用することでサーバー上からPDFのサイレント印刷が可能となります。

今回、Process.Startで呼び出す方式にしましたが、常駐プログラムにして特定の場所にファイルが配置されたら印刷するようにしてもいいと思います。

4
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3