ToPrinterWrapper 1.0.8
dotnet add package ToPrinterWrapper --version 1.0.8
NuGet\Install-Package ToPrinterWrapper -Version 1.0.8
<PackageReference Include="ToPrinterWrapper" Version="1.0.8" />
<PackageVersion Include="ToPrinterWrapper" Version="1.0.8" />
<PackageReference Include="ToPrinterWrapper" />
paket add ToPrinterWrapper --version 1.0.8
#r "nuget: ToPrinterWrapper, 1.0.8"
#:package ToPrinterWrapper@1.0.8
#addin nuget:?package=ToPrinterWrapper&version=1.0.8
#tool nuget:?package=ToPrinterWrapper&version=1.0.8
ToPrinterWrapper
A modern, dependency-injection-friendly .NET wrapper for 2Printer command-line printing automation, supporting asynchronous printing, concurrency control, robust testability, and ASP.NET Core integration.
Note: This wrapper requires 2Printer (by fCoder Group, Inc.), a commercial command-line printing tool. You must purchase a valid 2Printer license from cmd2printer.com to use this library in production.
Features
- Instance-based API for printing documents via 2Printer (DI/ASP.NET Core ready)
- Async (Task-based) methods with cancellation and concurrency support
- Print from file path, stream, or argument string
- Print options: copies, duplex, color, orientation, paper size, page range, scale, zoom, tray
- Concurrency control: limit the number of simultaneous print jobs (default 10, configurable)
- Robust temp file management and error handling
- Unit-testable and automation-friendly
- ASP.NET Core integration via
ToPrinterWrapperService
andToPrinterOptions
- Multi-targeting: .NET 6, 7, 8, 9
- Full XML documentation for all public APIs
- Example integration with Bullzip PDF Printer for automated PDF output
Usage
Dependency Injection (ASP.NET Core)
// In Program.cs or Startup.cs
services.Configure<ToPrinterOptions>(config =>
{
config.PrintPath = @"C:\\ToPrinter\\";
config.MaxConcurrentPrintingJobs = 5;
});
services.AddSingleton<ToPrinterWrapperService>();
Using ToPrinter in Your Code
public class MyService
{
private readonly ToPrinter _printer;
public MyService(ToPrinterWrapperService wrapper)
{
_printer = wrapper.Printer;
}
public async Task PrintAsync()
{
var options = new PrintOptions { Copies = 1, Duplex = DuplexMode.Simplex };
int exitCode = await _printer.PrintDocumentAsync("file.pdf", "Bullzip PDF Printer", options);
}
}
Print from Stream
using (var stream = File.OpenRead("file.pdf"))
{
await _printer.PrintDocumentAsync(stream, "Bullzip PDF Printer", options);
}
Customizing Print Options
var options = new PrintOptions
{
Copies = 2,
Duplex = DuplexMode.Vertical,
Color = ColorMode.Color,
Orientation = Orientation.Landscape,
PaperSize = PageSize.A4,
Pages = new PageRange("1-3,5"),
Scale = ScaleMode.Fit,
ZoomPercent = new ZoomLevel(120),
Tray = PrinterTray.Tray1
};
Using ToPrinterWrapper Without ASP.NET Core or Dependency Injection
You can use the ToPrinter
class directly in any .NET application, without ASP.NET Core or dependency injection. Simply create an instance and call its async methods:
var printer = new ToPrinter();
var options = new PrintOptions { Copies = 1 };
int exitCode = await printer.PrintDocumentAsync("file.pdf", "Bullzip PDF Printer", options);
This approach is suitable for console apps, WinForms, WPF, or any .NET project where you don't need DI or hosted services.
Speeding Up Temporary File Operations with a RAM Disk
For even faster print jobs and to reduce SSD wear, you can use a RAM disk for temporary files. This is especially useful when printing from streams, as the library writes the stream to a temporary file before printing.
Using OSFMount to Create a RAM Disk
You can use OSFMount to create a RAM disk. Example command to create a 1GB NTFS RAM disk mounted as drive R:
and labeled "PRINT":
& "C:\Program Files\OSFMount\osfmount.com" -a -t vm -m R: -o format:ntfs:"PRINT" -s 1G
# To unmount:
& "C:\Program Files\OSFMount\osfmount.com" -l -m R:
How to Use in Your Code
Set your temp file path to the RAM disk, for example:
string tempFile = Path.Combine(@"R:\", Path.GetRandomFileName() + ".pdf");
// Use tempFile for printing...
You can make the RAM disk path configurable in your application for flexibility.
Benefits:
- Much faster read/write speeds for temp files
- No SSD wear from temp file operations
- RAM disk contents are cleared on reboot
Automating RAM Disk Mounting at Startup (Windows)
To ensure the RAM disk is always available (e.g., after reboot), you can automate mounting using the provided scripts and Windows Task Scheduler:
Scripts Provided:
cmd/mount-ramdisk.cmd
— Mounts the RAM disk (R:) using OSFMount.cmd/unmount-ramdisk.cmd
— Unmounts the RAM disk (R:).cmd/install-mount-ramdisk-task.cmd
— Installs a Task Scheduler task to runmount-ramdisk.cmd
at startup with admin rights.cmd/uninstall-mount-ramdisk-task.cmd
— Removes the scheduled task.
How to Install the Startup Task:
- Open a terminal as Administrator.
- Run:
cd <path-to-ToPrinterWrapper\cmd> .\install-mount-ramdisk-task.cmd
- This will create a Task Scheduler entry named
MountRAMDisk
that runs at system startup with highest privileges.
How to Uninstall the Startup Task:
- Open a terminal as Administrator.
- Run:
cd <path-to-ToPrinterWrapper\cmd> .\uninstall-mount-ramdisk-task.cmd
Notes:
- The scripts must remain in their original folder, or you must update the scheduled task if you move them.
- The scheduled task uses an absolute path to ensure it works for all users.
- You can still run
mount-ramdisk.cmd
orunmount-ramdisk.cmd
manually if needed.
Memory Pressure Handling
ToPrinterWrapper includes a system-wide memory pressure safeguard:
- Automatic Throttling: If system memory usage exceeds a configurable threshold (default: 90% of physical RAM), new print jobs will wait until memory pressure is relieved before starting.
- No Exceptions or Errors: Threads are not rejected or failed due to memory pressure—they simply wait and retry until enough memory is available.
- Configuration:
MaxSystemMemoryUsageRatio
(default:0.9
) — The maximum allowed ratio of used system memory (e.g.,0.9
= 90%).MemoryPressurePollIntervalMs
(default:1000
) — How often (in milliseconds) to check for memory pressure relief while waiting.
- Platform: This feature uses native Windows APIs and is only available on Windows.
Example:
var printer = new ToPrinter { MaxSystemMemoryUsageRatio = 0.85, MemoryPressurePollIntervalMs = 2000 };
// If system memory usage is above 85%, new print jobs will wait and poll every 2 seconds.
This helps prevent system overload and ensures print jobs do not start when the system is under heavy memory pressure.
Memory Pressure Timeout
ToPrinterWrapper provides a configurable Memory Pressure Timeout feature to prevent print jobs from waiting indefinitely when the system is under heavy memory load.
What it does:
- When system memory usage exceeds the configured threshold (see
MaxSystemMemoryUsageRatio
), new print jobs will wait for memory pressure to be relieved up to a maximum timeout. - If memory pressure is not relieved within the timeout, the print job fails with a specific error code (
ErrorCode.MemoryPressureTimeout
).
- When system memory usage exceeds the configured threshold (see
How to configure:
MemoryPressureTimeoutMs
(default:60000
ms = 60 seconds)- The maximum time (in milliseconds) a print job will wait for system memory usage to drop below the threshold before giving up.
MaxSystemMemoryUsageRatio
(default:0.9
)- The maximum allowed ratio of used system memory (e.g.,
0.9
= 90%).
- The maximum allowed ratio of used system memory (e.g.,
MemoryPressurePollIntervalMs
(default:1000
)- How often (in milliseconds) to check for memory pressure relief while waiting.
Effect on Print Jobs:
- If the system is under memory pressure for longer than the timeout, the print job will fail fast instead of hanging indefinitely.
- The error code can be checked programmatically to distinguish this case from other failures.
Example:
var printer = new ToPrinter {
MaxSystemMemoryUsageRatio = 0.85,
MemoryPressurePollIntervalMs = 2000,
MemoryPressureTimeoutMs = 30000 // Wait up to 30 seconds
};
// If system memory usage is above 85%, new print jobs will wait and poll every 2 seconds, up to 30 seconds total.
Best Practices:
- Tune
MemoryPressureTimeoutMs
to balance between responsiveness and reliability for your workload. - Handle the
MemoryPressureTimeout
error code in your application to provide user feedback or retry logic as needed.
Error Code:
ErrorCode.MemoryPressureTimeout
(seeToPrinterWrapper.ErrorCodes.cs
)
Concurrency Testing
- The library can be tested for concurrency by launching multiple print jobs in parallel and verifying the maximum concurrency does not exceed the configured limit.
Error Handling & Troubleshooting
Example Error Handling
try
{
int exitCode = await printer.PrintDocumentAsync("file.pdf", "Bullzip PDF Printer", options);
if (exitCode != 0)
{
Console.WriteLine($"Printing failed: {exitCode} - {exitCode.ToDescription()}");
// Handle specific error codes as needed
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Printing was cancelled.");
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
}
Troubleshooting
- 2Printer.exe not found: Ensure 2Printer is installed and available in your PATH or working directory.
- RAM disk not available: If the configured print path (e.g.,
R:\
) does not exist, the library will fall back to the system temp directory. Check your RAM disk setup if you expect to use it. - Permission errors: Run your application with sufficient permissions to access printers and file paths.
- Printer not found or offline: Verify the printer name and network connectivity. Use
IsPrinterOnlineAsync
to check printer status. - File locked or not deleted: The library retries file deletion if a file is temporarily locked. If files remain, check for open handles or antivirus interference.
- Unhandled exceptions: Wrap print calls in try/catch and log or handle exceptions as appropriate for your application.
For more help, please open an issue on GitHub with details about your environment and error messages.
Thread Safety
The ToPrinterWrapper
class is mostly thread-safe for its intended usage, but with some caveats:
Feature/Method | Thread-Safe? | Notes |
---|---|---|
PrintDocumentAsync (all) | Yes* | Concurrency limited by semaphore. |
FileDeleteQueue | Yes | Uses thread-safe collections. |
Property Setters (Log, etc.) | No | Not synchronized; avoid concurrent writes. |
PrintOptions usage | No* | Do not share/mutate across threads. |
ShutdownAsync/DisposeAsync | Mostly | Minor race possible if called concurrently. |
Notice:
- Do not share or mutate
PrintOptions
across threads. - Avoid changing instance properties (
Log
,Silent
, etc.) while printing is in progress. - If you need to change configuration at runtime, create a new
ToPrinterWrapper
instance.
If you need full thread safety for property changes or shared configuration, consider adding locking or making the class immutable/configurable only at construction.
Requirements
- .NET 6.0 or later (multi-targets .NET 6, 7, 8, 9)
- 2Printer (must be purchased separately)
- 2Printer.exe in PATH or working directory
- (Optional) Bullzip PDF Printer for automated PDF output
Supported File Formats
ToPrinterWrapper (via 2Printer) supports printing more than 90 file formats (over 115 file extensions), including:
Internal Engine File Formats
2Printer (and thus ToPrinterWrapper) can print many file formats directly using its internal engine, without requiring additional software. These include:
- Images: TIFF, TIF, JPG, JPEG, JFIF, GIF, BMP, PNG, TGA, DCM, RAW, PSD, CDR, PCX, DCX, EMF, WMF, SVG, WEBP, JBIG, JBG, HEIC, HEIF, CALS
- Documents: PDF, XPS, OXPS, HTML, HTM, TXT, TEXT, JAVA, CSV, XML, EPUB, PRN, PS, RTF, OST, PST, P7M, EML, MSG, EMLX, ICS, ZPL, BAT, CMD, JS, VBS, PS1, PS1M
- CAD & Vector: DWG, DXF, DFT, SLDDRW, PLT, HPGL, HP, HPG, KDW, CDW, SPW
All File Formats
- Images: TIFF, JPG, JPEG, JFIF, GIF, BMP, PNG, TGA, DCM, RAW, PSD, CDR, PCX, DCX, EMF, WMF, SVG, SVGZ, WEBP, JBIG, JBG, HEIC, HEIF, CALS, and more
- Office Documents: PDF, DOC, DOCX, DOT, DOTX, XPS, OXPS, HTML, HTM, TXT, TEXT, JAVA, XLS, XLSX, XLSM, CSV, PPT, PPTX, PPSX, PUB, RTF, ODT, ODS, ODP, ODG, ODF, ONE, MHT, MHTML, VSD, VSDX, VSDM, WPC, SNP, XML, EPUB, and more
- CAD Drawings: DWG, DXF, DFT, SLDDRW, EPRT, EPRTX, EASM, EASMX, EDRW, EDRWX, SLDPRT, SLDASM, PRTDOT, ASMDOT, DRWDOT, 3DXML, STL, PLT, HPGL, HP, HPG, HPGL, KDW, CDW, SPW, IDW, IPT, IAM, IPN, MCDX, MCTX, and more
- Email Files: EML, MSG, OST, PST, P7M, EMLX
- Adobe Formats: PDF, INDD, INDP, IDAP, INDT, INDL, INX, IDML, QXD, QXT, INDB, PSD, SWF
- Other: ICS (iCalendar), ZPL (Zebra), PRN, PS, DWF, DWFX, DGN, CGM, CDR, CGM, BAT, CMD, JavaScript, VBS, PS1, PS1M, and more
Note: Some formats require additional software (e.g., Microsoft Office, Adobe InDesign, AutoCAD, KOMPAS-3D, CorelDraw, etc.) to be installed on the system. For a full, up-to-date list and software requirements, see the 2Printer Supported Formats page.
Common Supported Extensions:
.pdf, .doc, .docx, .dot, .dotx, .xls, .xlsx, .xlsm, .csv, .ppt, .pptx, .ppsx, .pub, .rtf, .odt, .ods, .odp, .odg, .one, .mht, .mhtml, .vsd, .vsdx, .vsdm, .wpc, .snp, .xml, .epub, .tif, .tiff, .jpg, .jpeg, .jfif, .gif, .bmp, .png, .tga, .dcm, .raw, .psd, .cdr, .pcx, .dcx, .emf, .wmf, .svg, .svgz, .webp, .jbig, .jbg, .heic, .heif, .dwg, .dxf, .dft, .slddrw, .eprt, .eprtx, .easm, .easmx, .edrw, .edrwx, .sldprt, .sldasm, .prtdot, .asmdot, .drwdot, .3dxml, .stl, .plt, .hp, .hpg, .hpgl, .kdw, .cdw, .spw, .idw, .ipt, .iam, .ipn, .mcdx, .mctx, .eml, .msg, .ost, .pst, .p7m, .emlx, .indd, .indp, .idap, .indt, .indl, .inx, .idml, .qxd, .qxt, .indb, .ps, .prn, .ics, .zpl, .bat, .cmd, .js, .vbs, .ps1, .ps1m
For the latest and complete list, always refer to the 2Printer Supported Formats page.
License
MIT License
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- Microsoft.Extensions.Hosting (>= 6.0.1)
- Microsoft.Extensions.Options (>= 6.0.1)
-
net7.0
- Microsoft.Extensions.Hosting (>= 7.0.1)
- Microsoft.Extensions.Options (>= 7.0.1)
-
net8.0
- Microsoft.Extensions.Hosting (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
-
net9.0
- Microsoft.Extensions.Hosting (>= 9.0.4)
- Microsoft.Extensions.Options (>= 9.0.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.0.8 | 149 | 5/11/2025 |