feat: 初始功能
This commit is contained in:
100
Services/Printing/PdfPrintJobExecutor.cs
Normal file
100
Services/Printing/PdfPrintJobExecutor.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using CloudPrint.Client.Models;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace CloudPrint.Client.Services.Printing;
|
||||
|
||||
public sealed class PdfPrintJobExecutor : IPrintJobExecutor
|
||||
{
|
||||
private readonly IWindowsPrintQueueService _queueService;
|
||||
|
||||
public PdfPrintJobExecutor(IWindowsPrintQueueService queueService)
|
||||
{
|
||||
_queueService = queueService;
|
||||
}
|
||||
|
||||
public bool CanHandle(PrintJob job)
|
||||
{
|
||||
return string.Equals(Path.GetExtension(job.FilePath), ".pdf", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(PrintJob job, IProgress<int>? progress, CancellationToken cancellationToken = default)
|
||||
{
|
||||
PrintFileGuards.EnsurePrintableFile(job);
|
||||
progress?.Report(10);
|
||||
|
||||
var sumatraPath = FindSumatraPdfExecutable();
|
||||
if (!string.IsNullOrWhiteSpace(sumatraPath))
|
||||
{
|
||||
await PrintWithSumatraAsync(sumatraPath, job, cancellationToken).ConfigureAwait(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
await PrintWithShellAsync(job, cancellationToken).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
CaptureWindowsJob(job);
|
||||
|
||||
progress?.Report(100);
|
||||
}
|
||||
|
||||
private void CaptureWindowsJob(PrintJob job)
|
||||
{
|
||||
var documentName = Path.GetFileName(job.FilePath);
|
||||
var queueJob = _queueService.FindLatestJob(job.PrinterName, documentName);
|
||||
if (queueJob is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
job.WindowsJobId = queueJob.JobId;
|
||||
job.WindowsJobStatus = queueJob.Status;
|
||||
}
|
||||
|
||||
private static async Task PrintWithSumatraAsync(string sumatraPath, PrintJob job, CancellationToken cancellationToken)
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = sumatraPath,
|
||||
Arguments = $"-print-to \"{job.PrinterName}\" -silent -exit-when-done \"{job.FilePath}\"",
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
using var process = Process.Start(startInfo) ?? throw new InvalidOperationException("启动 SumatraPDF 失败");
|
||||
await process.WaitForExitAsync(cancellationToken).ConfigureAwait(true);
|
||||
if (process.ExitCode != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"SumatraPDF 打印失败,退出码:{process.ExitCode}");
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task PrintWithShellAsync(PrintJob job, CancellationToken cancellationToken)
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = job.FilePath,
|
||||
Verb = "printto",
|
||||
Arguments = $"\"{job.PrinterName}\"",
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
};
|
||||
|
||||
using var process = Process.Start(startInfo)
|
||||
?? throw new InvalidOperationException("无法调用系统默认 PDF 打印程序,请安装 SumatraPDF 或配置 PDF 默认打印程序");
|
||||
await process.WaitForExitAsync(cancellationToken).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
private static string? FindSumatraPdfExecutable()
|
||||
{
|
||||
var candidates = new[]
|
||||
{
|
||||
Environment.GetEnvironmentVariable("SUMATRA_PDF_PATH"),
|
||||
@"C:\Program Files\SumatraPDF\SumatraPDF.exe",
|
||||
@"C:\Program Files (x86)\SumatraPDF\SumatraPDF.exe"
|
||||
};
|
||||
|
||||
return candidates.FirstOrDefault(path => !string.IsNullOrWhiteSpace(path) && File.Exists(path));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user