LibreOfficeKit 1.0.6

dotnet add package LibreOfficeKit --version 1.0.6
                    
NuGet\Install-Package LibreOfficeKit -Version 1.0.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LibreOfficeKit" Version="1.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LibreOfficeKit" Version="1.0.6" />
                    
Directory.Packages.props
<PackageReference Include="LibreOfficeKit" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LibreOfficeKit --version 1.0.6
                    
#r "nuget: LibreOfficeKit, 1.0.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LibreOfficeKit@1.0.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LibreOfficeKit&version=1.0.6
                    
Install as a Cake Addin
#tool nuget:?package=LibreOfficeKit&version=1.0.6
                    
Install as a Cake Tool

LibreOfficeKit

A .NET library and console application for document-to-PDF conversion using LibreOfficeKit, featuring a multi-process worker pool for safe concurrent conversions.

NuGet

NuGet

Using it on Windows

At the moment this package does not work with Excel and Powerpoint files on Windows, I have raised a ticket for this --> https://bugs.documentfoundation.org/show_bug.cgi?id=172283

Update: It seems to be a problem with LibreOffice versions newer than 25.2.6.2, so if you install this version it will work

Documentation

Documentation

Full API reference documentation (generated by DocFX) is published automatically to GitHub Pages on every push to main:
https://sicos1977.github.io/LibreOfficeKit

Architecture

LibreOfficeKit (LOK) is not thread-safe — only one instance per process is allowed. To enable concurrent conversions, this project uses a process pool architecture:

  • The host process (Converter) manages a pool of isolated worker processes.
  • Each worker connects via a named pipe, initializes its own LOK instance, and processes one request at a time.
  • The host dispatches conversion requests to free workers and queues requests when all workers are busy.
  • Workers are health-monitored via periodic pings and recycled if they crash or hang.

Solution Structure

Project Type Target Description
LibreOfficeKit Class Library .NET Standard 2.0 Core library: Converter, WorkerProcess, IPC, LOK bindings, Enums
LibreOfficeKitWorker Console App .NET 10 Worker entry point and optional standalone demo
LibreOfficeTest Test Project .NET 10 MSTest integration tests

LibreOfficeKitWorker (Console App)

File Description
Program.cs Worker entry point; also supports a standalone demo/test mode

Features

  • Hot standby: Pre-spawned workers for immediate conversion
  • On-demand scaling: Scale up to maxInstances as needed
  • Idle timeout: Excess workers shut down automatically after an idle period
  • Health monitoring: Background pings detect crashed or hung workers
  • Request queuing: Requests queue when all workers are busy
  • Conversion timeout: Optional per-call timeout with TimeoutException
  • Stream support: Convert from/to Stream (uses temp files internally)
  • PDF options: Full control over PDF export quality, compliance, security and layout via PdfOptions
  • Enum-based API: Type-safe save formats and document types
  • Proper disposal: IDisposable and IAsyncDisposable for clean shutdown

Usage

Basic conversion (file paths)

using LibreOfficeKit;

await using var converter = new Converter(
    maxInstances: 4,
    minHotStandby: 2,
    idleTimeout: TimeSpan.FromMinutes(5));

await converter.ConvertToPdfAsync("input.docx", "output.pdf");

With a timeout

await converter.ConvertToPdfAsync(
    "input.docx",
    "output.pdf",
    timeout: TimeSpan.FromSeconds(30));

With PDF options

using LibreOfficeKit;

var options = new PdfOptions
{
    Quality            = 95,
    ReduceImageResolution = true,
    MaxImageResolutionDpi = 150,
    UseTaggedPdf       = true,
    ExportBookmarks    = true,
    PageRange          = "1-10"
};

await converter.ConvertToPdfAsync("input.docx", "output.pdf", pdfOptions: options);

Using a preset

await converter.ConvertToPdfAsync(
    "input.docx",
    "output.pdf",
    pdfOptions: PdfOptions.Archive);   // PDF/A-2b archival preset

Stream conversion

await using var input  = File.OpenRead("input.docx");
await using var output = File.Create("output.pdf");

await converter.ConvertToPdfAsync(input, output, pdfOptions: PdfOptions.Screen);

Exception Handling

The library uses specific exception types to distinguish between different failure scenarios during document loading and conversion. All custom exceptions are in the LibreOfficeKit.Exceptions namespace.

Exception Types

Exception When thrown
TimeoutException The conversion or worker operation exceeded the specified timeout
DocumentPasswordProtectedException The document is password-protected and cannot be opened without credentials
FileTypeNotSupportedException The file type is not supported by LibreOffice for loading or conversion
ConversionFailedException The conversion failed for any other reason

Exception Flow

Exceptions originate in the worker process and are propagated to the calling code through the IPC layer:

Worker Process: Document.Load / Document.SaveAs
     ↓
Worker: Catches specific exception (e.g., DocumentPasswordProtectedException)
     ↓
Worker: Sends ConvertResponse with ExceptionType field
     ↓
Converter: Reads ExceptionType and re-throws the original exception type
     ↓
Your Code: Can catch specific exception types

Usage Example

using LibreOfficeKit;
using LibreOfficeKit.Exceptions;

await using var converter = new Converter(maxInstances: 4);

try
{
    await converter.ConvertToPdfAsync("input.docx", "output.pdf");
}
catch (FilePasswordProtectedException ex)
{
    // File requires a password
    Console.WriteLine($"File is password-protected: {ex.Message}");
}
catch (FileTypeNotSupportedException ex)
{
    // File type not supported by LibreOffice
    Console.WriteLine($"File type not supported: {ex.Message}");
}
catch (TimeoutException ex)
{
    // Conversion took too long
    Console.WriteLine($"Conversion timed out: {ex.Message}");
}
catch (ConversionFailedException ex)
{
    // Other conversion failure
    Console.WriteLine($"Conversion failed: {ex.Message}");
}

Detection Logic

The library analyzes error messages returned by LibreOffice to determine the exception type:

  • Password-protected: Error contains "password", "encrypted", or "protected"
  • Unsupported file type: Error contains "format", "not supported", "unknown", or "filter"
  • Timeout: Operation exceeds the specified timeout parameter
  • Other failures: Any other error during loading or conversion

Timeout Behavior

When a timeout is specified, the library enforces it at multiple stages:

  1. Worker acquisition: Waiting for an available worker
  2. Worker spawn: Starting a new worker process
  3. Document loading: Loading the input document in the worker
  4. PDF conversion: Converting and saving the PDF
  5. IPC communication: Sending requests and reading responses

If any stage exceeds the remaining time budget, a TimeoutException is thrown immediately.

PdfOptions Reference

PdfOptions controls how LibreOffice exports the PDF. Pass an instance as the pdfOptions parameter of ConvertToPdfAsync.

Image quality

Property Type Default Description
UseLosslessCompression bool false Use lossless (PNG) compression for images instead of JPEG
Quality int 90 JPEG compression quality (1–100). Higher = better quality, larger file
ReduceImageResolution bool true Down-sample images that exceed MaxImageResolutionDpi
MaxImageResolutionDpi int 300 Maximum DPI for embedded images when ReduceImageResolution is true

Content & accessibility

Property Type Default Description
ExportBookmarks bool true Include document headings as PDF bookmarks/outlines
ExportNotes bool false Include document comments/annotations
ExportFormFields bool true Export form fields as interactive PDF widgets
UseTaggedPdf bool false Create a tagged PDF (required for PDF/UA accessibility)
SinglePageSheets bool false Fit each spreadsheet sheet onto a single PDF page

Compliance & version

Property Type Default Description
PdfACompliance PdfACompliance None PDF/A archival standard (None, Level1b, Level2b, Level3b)
PdfVersion PdfVersion? null (LOK default) Target PDF version (PDF14, PDF15, PDF16, PDF17, PdfA1b, PdfA2b, PdfUA1)

When PdfVersion is set it takes precedence over PdfACompliance.

Layout

Property Type Default Description
PageRange string? null (all) Page range to export, e.g. "1-5" or "2,4"
Watermark string? null Watermark text printed on every page
InitialView InitialView Default Which panel is shown when the PDF is opened (Default, Bookmarks, Thumbnails)

Security

Property Type Default Description
EncryptionPassword string? null Password required to open the PDF (simple encryption)
Security PdfSecurityOptions? null Full security settings: passwords, printing and change permissions

PdfSecurityOptions properties:

Property Type Description
EncryptFile bool Enable encryption
DocumentOpenPassword string? Password to open the document
RestrictPermissions bool Enable permission restrictions
PermissionPassword string? Password required to change permissions
Printing PdfPrintPermission? Print permission level (NotPermitted, LowResolution, HighResolution)
Changes PdfChangePermission? Change permission level (NotPermitted, OnlyComments, OnlyFormFields, …)
EnableCopyingOfContent bool? Allow copying text/images
EnableTextAccessForAccessibilityTools bool? Allow screen readers

Advanced compression overrides

Set Compression (PdfCompressionOptions) to override image compression settings per image type rather than using the top-level UseLosslessCompression/Quality properties.

Property Type Description
UseLosslessCompression bool? Override lossless flag
Quality int? Override JPEG quality (1–100)
ReduceImageResolution bool? Override resolution reduction flag
MaxImageResolution int? Override maximum DPI

Built-in presets

Preset Description
PdfOptions.HighQuality Lossless compression, full resolution, tagged PDF — for archiving
PdfOptions.Screen JPEG 85%, 150 DPI — small file size optimised for on-screen use
PdfOptions.Print JPEG 90%, 300 DPI — balanced quality for printing
PdfOptions.Archive JPEG 90%, 300 DPI, tagged, PDF/A-2b — long-term archival

Advanced Features

Optional Features (LibreOffice 6.0+)

LibreOfficeKit supports optional features that modify callback behavior and rendering. These are primarily useful for interactive viewers and collaborative editing scenarios.

Available Features:

Feature Description
DocumentPassword Enable password prompts for encrypted documents
DocumentPasswordToModify Enable password prompts for write-protected documents
PartInInvalidationCallback Include part number in tile invalidation callbacks
NoTiledAnnotations Disable annotation rendering (performance optimization)
RangeHeaders Enable range-based spreadsheet header queries
ViewIdInVisibleCursorInvalidationCallback Include view ID in cursor callbacks (multi-user)

Example - Optimize for Conversion:

using LibreOfficeKit;
using LibreOfficeKit.Enums;

// Direct LOK instance (for advanced scenarios)
var instance = Instance.Create(@"C:\Program Files\LibreOffice\program");

// Disable annotation rendering for faster conversion
instance.SetOptionalFeatures(OptionalFeatures.NoTiledAnnotations);

var doc = instance.DocumentLoad(Instance.PathToFileUrl(@"C:\input.docx"));
doc.SaveAs(Instance.PathToFileUrl(@"C:\output.pdf"), "pdf");
doc.Dispose();
instance.Dispose();

Example - Password-Protected Documents:

var instance = Instance.Create(installPath);

// Enable password features
instance.SetOptionalFeatures(
    OptionalFeatures.DocumentPassword | 
    OptionalFeatures.DocumentPasswordToModify);

// Pre-register password for a specific document
var fileUrl = Instance.PathToFileUrl(@"C:\encrypted.docx");
instance.SetDocumentPassword(fileUrl, "myPassword123");

// Load will now use the password automatically
var doc = instance.DocumentLoad(fileUrl);
doc.SaveAs(outputUrl, "pdf");

📖 See OPTIONAL_FEATURES.md for detailed documentation.

Direct LibreOfficeKit Instance

For advanced scenarios where you need direct control over LibreOfficeKit (without the worker pool), use Instance directly:

using LibreOfficeKit;

var installPath = Instance.FindInstallPath() 
    ?? @"C:\Program Files\LibreOffice\program";

using var instance = Instance.Create(installPath);

var inputUrl = Instance.PathToFileUrl(@"C:\input.docx");
var outputUrl = Instance.PathToFileUrl(@"C:\output.pdf");

using var doc = instance.DocumentLoad(inputUrl);
doc.SaveAs(outputUrl, "pdf");

⚠️ Note: Only one Instance can be active per process. Use Converter for concurrent conversions.

Prerequisites

Documentation

The full API reference is published automatically to GitHub Pages on every push to main:

https://sicos1977.github.io/LibreOfficeKit

Build

dotnet build LibreOfficeKit.sln

NuGet Package

How it works

The LibreOfficeKit NuGet package bundles the LibreOfficeKitWorker worker executable for all supported platforms. The worker is a self-contained, trimmed single-file binary — no .NET installation is required on the target machine.

When the package is installed in a consuming project, the MSBuild targets file (build/LibreOfficeKit.targets) that ships inside the package automatically copies the correct worker executable for the current platform to the project's output directory at build time. No manual steps are needed.

Package contents

build/
  LibreOfficeKit.targets          ← MSBuild targets, auto-copies the right worker exe
runtimes/
  win-x64/native/
    LibreOfficeKitWorker.exe    ← Self-contained worker for Windows x64
  linux-x64/native/
    LibreOfficeKitWorker        ← Self-contained worker for Linux x64
  osx-x64/native/
    LibreOfficeKitWorker        ← Self-contained worker for macOS Intel
  osx-arm64/native/
    LibreOfficeKitWorker        ← Self-contained worker for macOS Apple Silicon
lib/
  net10.0/LibreOfficeKit.dll
  netstandard2.0/LibreOfficeKit.dll

Building the package locally

Building the package requires the cross-platform publish tools included with .NET 10.

dotnet pack LibreOfficeKit/LibreOfficeKit.csproj -c Release

During packing, MSBuild automatically publishes LibreOfficeKitWorker for all four runtime identifiers (win-x64, linux-x64, osx-x64, osx-arm64) before assembling the package. The resulting files are staged in LibreOfficeKit/_WorkerPublish/ (excluded from source control via .gitignore) and then embedded in the .nupkg.

The output is written to:

LibreOfficeKit/bin/Release/LibreOfficeKit.<version>.nupkg
LibreOfficeKit/bin/Release/LibreOfficeKit.<version>.snupkg   ← debug symbols

Versioning

The package version is set via the <Version> property in LibreOfficeKit/LibreOfficeKit.csproj. Update it before packing a new release:

<Version>1.2.0</Version>
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  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 was computed.  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 was computed.  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 was computed.  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 is compatible.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.6 72 6/8/2026
1.0.0 69 6/1/2026

- Renamed LibreOfficeKit.Console.exe to LibreOfficeKitWorker.exe