commits
tags
using System.Diagnostics;
using Remiss.Core.Abstractions;
namespace Remiss.Core.Printing;
/// <summary>
/// Tyst utskrift via buntad SumatraPDF. Retry-logik eftersom spooler/skrivare
/// tidvis är otillgänglig.
/// </summary>
public sealed class SumatraPdfPrinter : IPrinter
{
private readonly string _exePath;
private readonly int _retries;
private readonly int _retryDelayMs;
public SumatraPdfPrinter(string exePath, int retries = 3, int retryDelayMs = 2000)
{
_exePath = exePath;
_retries = Math.Max(1, retries);
_retryDelayMs = Math.Max(0, retryDelayMs);
}
/// <param name="printerName">
/// Namngiven skrivare, eller tom/null för Windows standardskrivare.
/// </param>
public void Print(string pdfPath, string? printerName)
{
if (!File.Exists(_exePath))
throw new FileNotFoundException(
$"SumatraPDF hittades inte: {_exePath}. Lägg binären i tools/ (se tools/README.md).", _exePath);
Exception? last = null;
for (var attempt = 1; attempt <= _retries; attempt++)
{
try
{
RunOnce(pdfPath, printerName);
return;
}
catch (Exception ex)
{
last = ex;
if (attempt < _retries)
Thread.Sleep(_retryDelayMs);
}
}
throw new InvalidOperationException($"Utskrift misslyckades efter {_retries} försök.", last);
}
private void RunOnce(string pdfPath, string? printerName)
{
var psi = new ProcessStartInfo
{
FileName = _exePath,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
};
if (string.IsNullOrWhiteSpace(printerName))
{
psi.ArgumentList.Add("-print-to-default");
}
else
{
psi.ArgumentList.Add("-print-to");
psi.ArgumentList.Add(printerName);
}
psi.ArgumentList.Add("-silent");
psi.ArgumentList.Add(pdfPath);
using var proc = Process.Start(psi)
?? throw new InvalidOperationException("Kunde inte starta SumatraPDF.");
if (!proc.WaitForExit(60_000))
{
try { proc.Kill(entireProcessTree: true); } catch { /* ignore */ }
throw new TimeoutException("SumatraPDF svarade inte inom 60 sekunder.");
}
if (proc.ExitCode != 0)
{
var err = proc.StandardError.ReadToEnd().Trim();
throw new InvalidOperationException(
$"SumatraPDF avslutades med kod {proc.ExitCode}." + (err.Length > 0 ? $" {err}" : ""));
}
}
}