How to Migrate from Ghostscript GPL to IronPDF in C#
Migrating from Ghostscript to IronPDF moves your .NET PDF workflow off command-line process spawning and string-based switch manipulation onto a typed, IntelliSense-enabled native .NET API. This guide walks through a step-by-step migration path that removes AGPL-3.0 licensing exposure and the external native binary dependency.
A note on terminology: Ghostscript (by Artifex Software) is dual-licensed under AGPL-3.0 or a commercial license, not plain GPL. The "GPL" tag is a long-standing community shorthand for the open-source build; everything in this guide refers to the AGPL-3.0 build of Ghostscript and the Ghostscript.NET wrapper (which is also AGPL-3.0 / commercial-dual). From .NET, Ghostscript is typically consumed via that wrapper, which P/Invokes the native gsdll32.dll / gsdll64.dll, or by shelling out to gswin32c / gswin64c via Process.Start.
Why Migrate from Ghostscript to IronPDF
The Ghostscript Challenges
Ghostscript is a long-standing PostScript/PDF interpreter from Artifex Software with decades of history. Its use in modern .NET applications presents several practical challenges:
-
AGPL-3.0 License Restrictions: Both Ghostscript itself and the
Ghostscript.NETwrapper are dual-licensed under AGPL-3.0 or a commercial license from Artifex. AGPL's network-copyleft clause typically requires that you release the corresponding source of the larger work — including for SaaS / network use — unless you purchase a commercial license. This often rules out the AGPL build for closed-source or hosted .NET applications. -
Command-Line Interface: Ghostscript is fundamentally a command-line tool. Using it from C# means spawning processes, passing string arguments, and parsing output — either via
Process.Startagainstgswin*c.exeor via theGhostscript.NETP/Invoke wrapper. -
External Binary Dependency: You must install Ghostscript separately, manage PATH variables, and keep versions aligned across environments. Different native DLLs are required for 32-bit vs 64-bit (
gsdll32.dllvsgsdll64.dll). -
No Native HTML-to-PDF: Ghostscript cannot convert HTML to PDF directly. You first need to convert HTML to PostScript with another tool, then run Ghostscript to convert PostScript to PDF — a multi-step pipeline with external dependencies.
-
Complex Switch Syntax: Operations are controlled via command-line switches like
-dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=.... No IntelliSense, no compile-time checks. -
Error Handling: Errors come through stderr as text strings, requiring parsing rather than structured exception handling.
- Process Management Overhead: Each operation spawns a separate process, adding overhead and complexity for timeouts and resource cleanup.
Ghostscript vs IronPDF Comparison
| Aspect | Ghostscript | IronPDF |
|---|---|---|
| License | AGPL-3.0 (network-copyleft) or Artifex commercial | Commercial with clear terms |
| Integration | Command-line process spawning | Native .NET library |
| API Design | String-based switches | Typed, IntelliSense-enabled API |
| Error Handling | Parse stderr text | .NET exceptions |
| HTML-to-PDF | Not supported (need external tools) | Built-in Chromium engine |
| Dependencies | External binary installation | Self-contained NuGet package |
| Deployment | Configure PATH, copy DLLs | Just add NuGet reference |
| Thread Safety | Process isolation only | Thread-safe by design |
| Modern .NET | Ghostscript.NET v1.3.x targets .NET Standard 2.0 |
.NET Framework 4.6.2+ and .NET 6/7/8/9 |
| Async Support | Process-based | Native async/await |
Migration Complexity Assessment
Estimated Effort by Feature
| Feature | Migration Complexity |
|---|---|
| PDF to Images | Low |
| Merge PDFs | Low |
| Compress PDF | Low |
| PDF Optimization | Low |
| Encryption | Medium |
| Page Extraction | Low |
| PostScript to PDF | Medium-High |
| Custom Switches | Medium-High |
Paradigm Shift
The fundamental shift in this Ghostscript migration is from command-line process execution to typed .NET API calls:
Ghostscript: "Pass these string switches to an external process"
IronPDF: "Call these methods on .NET objects"
Before You Start
Prerequisites
- .NET Version: IronPDF supports .NET Framework 4.6.2+ and .NET Core / .NET 5+ (including .NET 6/7/8/9).
Ghostscript.NETv1.3.x targets .NET Standard 2.0. - License Key: Obtain your IronPDF license key from ironpdf.com
- Backup: Create a branch for migration work
Identify All Ghostscript Usage
# Find all Ghostscript.NET references
grep -r "Ghostscript\.NET\|GhostscriptProcessor\|GhostscriptRasterizer\|gsdll" --include="*.cs" .
# Find direct process calls to Ghostscript
grep -r "gswin64c\|gswin32c\|gs\|ProcessStartInfo.*ghost" --include="*.cs" .
# Find package references
grep -r "Ghostscript" --include="*.csproj" .
# Find all Ghostscript.NET references
grep -r "Ghostscript\.NET\|GhostscriptProcessor\|GhostscriptRasterizer\|gsdll" --include="*.cs" .
# Find direct process calls to Ghostscript
grep -r "gswin64c\|gswin32c\|gs\|ProcessStartInfo.*ghost" --include="*.cs" .
# Find package references
grep -r "Ghostscript" --include="*.csproj" .
NuGet Package Changes
# Remove Ghostscript.NET
dotnet remove package Ghostscript.NET
# Install IronPDF
dotnet add package IronPdf
# Remove Ghostscript.NET
dotnet remove package Ghostscript.NET
# Install IronPDF
dotnet add package IronPdf
Remove Ghostscript Dependencies
After migration:
- Uninstall Ghostscript from servers
- Remove
gsdll32.dll/gsdll64.dllfrom deployments - Remove PATH configuration for Ghostscript
- Remove any
GhostscriptVersionInforeferences
Quick Start Migration
Step 1: Update License Configuration
Before (Ghostscript):
Ghostscript under AGPL-3.0 requires either source disclosure under AGPL terms or a commercial license from Artifex.
After (IronPDF):
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
Step 2: Update Namespace Imports
// Before (Ghostscript)
using Ghostscript.NET;
using Ghostscript.NET.Processor;
using Ghostscript.NET.Rasterizer;
// After (IronPDF)
using IronPdf;
// Before (Ghostscript)
using Ghostscript.NET;
using Ghostscript.NET.Processor;
using Ghostscript.NET.Rasterizer;
// After (IronPDF)
using IronPdf;
Imports Ghostscript.NET
Imports Ghostscript.NET.Processor
Imports Ghostscript.NET.Rasterizer
' After (IronPDF)
Imports IronPdf
Complete API Reference
Core Class Mapping
| Ghostscript.NET | IronPDF | Description |
|---|---|---|
GhostscriptProcessor |
Various PdfDocument methods |
PDF processing |
GhostscriptRasterizer |
PdfDocument.RasterizeToImageFiles() |
PDF to images |
GhostscriptVersionInfo |
N/A (not needed) | DLL location |
GhostscriptStdIO |
N/A (use exceptions) | I/O handling |
| Process + command-line | ChromePdfRenderer |
HTML to PDF |
Command-Line Switch Mapping
| Ghostscript Switch | IronPDF Equivalent | Description |
|---|---|---|
-dNOPAUSE |
N/A (not needed) | Don't pause between pages |
-dBATCH |
N/A (not needed) | Exit after processing |
-dSAFER |
N/A (default) | Safe file access |
-sDEVICE=pdfwrite |
Various PDF methods | Output PDF |
-sDEVICE=png16m |
RasterizeToImageFiles("*.png", DPI: N) |
PNG output |
-sOutputFile=X |
SaveAs("X") |
Output filename |
-r300 |
DPI: 300 parameter |
Resolution |
-dPDFSETTINGS=/ebook |
CompressImages(quality: 60) |
Medium quality |
-dFirstPage=N -dLastPage=M |
CopyPages(new[] {N-1, ..., M-1}) |
Page extraction (0-indexed) |
-sOwnerPassword=X |
SecuritySettings.OwnerPassword |
Owner password |
-sUserPassword=X |
SecuritySettings.UserPassword |
User password |
Code Migration Examples
Example 1: HTML to PDF Conversion
Before (Ghostscript):
// NuGet: Install-Package Ghostscript.NET
using Ghostscript.NET;
using Ghostscript.NET.Processor;
using System.IO;
using System.Text;
class GhostscriptExample
{
static void Main()
{
// Ghostscript cannot directly convert HTML to PDF
// You need to first convert HTML to PS/EPS using another tool
// then use Ghostscript to convert PS to PDF
string htmlContent = "<html><body><h1>Hello World</h1></body></html>";
string psFile = "temp.ps";
string outputPdf = "output.pdf";
// This is a workaround - Ghostscript primarily works with PostScript
GhostscriptProcessor processor = new GhostscriptProcessor();
List<string> switches = new List<string>
{
"-dNOPAUSE",
"-dBATCH",
"-dSAFER",
"-sDEVICE=pdfwrite",
$"-sOutputFile={outputPdf}",
psFile
};
processor.Process(switches.ToArray());
}
}
// NuGet: Install-Package Ghostscript.NET
using Ghostscript.NET;
using Ghostscript.NET.Processor;
using System.IO;
using System.Text;
class GhostscriptExample
{
static void Main()
{
// Ghostscript cannot directly convert HTML to PDF
// You need to first convert HTML to PS/EPS using another tool
// then use Ghostscript to convert PS to PDF
string htmlContent = "<html><body><h1>Hello World</h1></body></html>";
string psFile = "temp.ps";
string outputPdf = "output.pdf";
// This is a workaround - Ghostscript primarily works with PostScript
GhostscriptProcessor processor = new GhostscriptProcessor();
List<string> switches = new List<string>
{
"-dNOPAUSE",
"-dBATCH",
"-dSAFER",
"-sDEVICE=pdfwrite",
$"-sOutputFile={outputPdf}",
psFile
};
processor.Process(switches.ToArray());
}
}
Imports Ghostscript.NET
Imports Ghostscript.NET.Processor
Imports System.IO
Imports System.Text
Class GhostscriptExample
Shared Sub Main()
' Ghostscript cannot directly convert HTML to PDF
' You need to first convert HTML to PS/EPS using another tool
' then use Ghostscript to convert PS to PDF
Dim htmlContent As String = "<html><body><h1>Hello World</h1></body></html>"
Dim psFile As String = "temp.ps"
Dim outputPdf As String = "output.pdf"
' This is a workaround - Ghostscript primarily works with PostScript
Dim processor As New GhostscriptProcessor()
Dim switches As New List(Of String) From {
"-dNOPAUSE",
"-dBATCH",
"-dSAFER",
"-sDEVICE=pdfwrite",
$"-sOutputFile={outputPdf}",
psFile
}
processor.Process(switches.ToArray())
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class IronPdfExample
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
string htmlContent = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class IronPdfExample
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var renderer = new ChromePdfRenderer();
string htmlContent = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Class IronPdfExample
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim renderer As New ChromePdfRenderer()
Dim htmlContent As String = "<html><body><h1>Hello World</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("output.pdf")
End Sub
End Class
Ghostscript cannot directly convert HTML to PDF — it expects PostScript or PDF input, so an HTML workflow requires an intermediate conversion (typically via wkhtmltopdf or similar). IronPDF's ChromePdfRenderer provides direct HTML-to-PDF rendering with CSS, JavaScript, and modern web standards support via an embedded Chromium engine. See the HTML to PDF documentation for more rendering options.
Example 2: PDF to Images
Before (Ghostscript):
// NuGet: Install-Package Ghostscript.NET
using Ghostscript.NET;
using Ghostscript.NET.Rasterizer;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
class GhostscriptExample
{
static void Main()
{
string inputPdf = "input.pdf";
string outputPath = "output";
GhostscriptVersionInfo gvi = new GhostscriptVersionInfo("gsdll64.dll");
using (GhostscriptRasterizer rasterizer = new GhostscriptRasterizer())
{
rasterizer.Open(inputPdf, gvi, false);
for (int pageNumber = 1; pageNumber <= rasterizer.PageCount; pageNumber++)
{
Image img = rasterizer.GetPage(300, pageNumber);
img.Save($"{outputPath}_page{pageNumber}.png", ImageFormat.Png);
img.Dispose();
}
}
}
}
// NuGet: Install-Package Ghostscript.NET
using Ghostscript.NET;
using Ghostscript.NET.Rasterizer;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
class GhostscriptExample
{
static void Main()
{
string inputPdf = "input.pdf";
string outputPath = "output";
GhostscriptVersionInfo gvi = new GhostscriptVersionInfo("gsdll64.dll");
using (GhostscriptRasterizer rasterizer = new GhostscriptRasterizer())
{
rasterizer.Open(inputPdf, gvi, false);
for (int pageNumber = 1; pageNumber <= rasterizer.PageCount; pageNumber++)
{
Image img = rasterizer.GetPage(300, pageNumber);
img.Save($"{outputPath}_page{pageNumber}.png", ImageFormat.Png);
img.Dispose();
}
}
}
}
Imports Ghostscript.NET
Imports Ghostscript.NET.Rasterizer
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Class GhostscriptExample
Shared Sub Main()
Dim inputPdf As String = "input.pdf"
Dim outputPath As String = "output"
Dim gvi As New GhostscriptVersionInfo("gsdll64.dll")
Using rasterizer As New GhostscriptRasterizer()
rasterizer.Open(inputPdf, gvi, False)
For pageNumber As Integer = 1 To rasterizer.PageCount
Dim img As Image = rasterizer.GetPage(300, pageNumber)
img.Save($"{outputPath}_page{pageNumber}.png", ImageFormat.Png)
img.Dispose()
Next
End Using
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class IronPdfExample
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var pdf = PdfDocument.FromFile("input.pdf");
// One-shot: write every page as PNG matching Ghostscript's -r300 -sDEVICE=png16m
pdf.RasterizeToImageFiles("output_page*.png", DPI: 300);
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class IronPdfExample
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var pdf = PdfDocument.FromFile("input.pdf");
// One-shot: write every page as PNG matching Ghostscript's -r300 -sDEVICE=png16m
pdf.RasterizeToImageFiles("output_page*.png", DPI: 300);
}
}
Imports IronPdf
Imports System
Class IronPdfExample
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim pdf = PdfDocument.FromFile("input.pdf")
' One-shot: write every page as PNG matching Ghostscript's -r300 -sDEVICE=png16m
pdf.RasterizeToImageFiles("output_page*.png", DPI:=300)
End Sub
End Class
The Ghostscript approach requires locating the external gsdll64.dll, creating a GhostscriptVersionInfo object, and iterating pages with 1-indexed page numbers. IronPDF's RasterizeToImageFiles writes every page in a single call with a glob output pattern and an explicit DPI: parameter, with no external native dependency. Note that when you do work with page indices, Ghostscript uses 1-indexed pages while IronPDF uses 0-indexed pages (standard .NET convention).
Example 3: Merge PDF Files
Before (Ghostscript):
// NuGet: Install-Package Ghostscript.NET
using Ghostscript.NET;
using Ghostscript.NET.Processor;
using System.Collections.Generic;
class GhostscriptExample
{
static void Main()
{
string outputPdf = "merged.pdf";
string[] inputFiles = { "file1.pdf", "file2.pdf", "file3.pdf" };
GhostscriptProcessor processor = new GhostscriptProcessor();
List<string> switches = new List<string>
{
"-dNOPAUSE",
"-dBATCH",
"-dSAFER",
"-sDEVICE=pdfwrite",
$"-sOutputFile={outputPdf}"
};
switches.AddRange(inputFiles);
processor.Process(switches.ToArray());
}
}
// NuGet: Install-Package Ghostscript.NET
using Ghostscript.NET;
using Ghostscript.NET.Processor;
using System.Collections.Generic;
class GhostscriptExample
{
static void Main()
{
string outputPdf = "merged.pdf";
string[] inputFiles = { "file1.pdf", "file2.pdf", "file3.pdf" };
GhostscriptProcessor processor = new GhostscriptProcessor();
List<string> switches = new List<string>
{
"-dNOPAUSE",
"-dBATCH",
"-dSAFER",
"-sDEVICE=pdfwrite",
$"-sOutputFile={outputPdf}"
};
switches.AddRange(inputFiles);
processor.Process(switches.ToArray());
}
}
Imports Ghostscript.NET
Imports Ghostscript.NET.Processor
Imports System.Collections.Generic
Class GhostscriptExample
Shared Sub Main()
Dim outputPdf As String = "merged.pdf"
Dim inputFiles As String() = {"file1.pdf", "file2.pdf", "file3.pdf"}
Dim processor As New GhostscriptProcessor()
Dim switches As New List(Of String) From {
"-dNOPAUSE",
"-dBATCH",
"-dSAFER",
"-sDEVICE=pdfwrite",
$"-sOutputFile={outputPdf}"
}
switches.AddRange(inputFiles)
processor.Process(switches.ToArray())
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System.Collections.Generic;
class IronPdfExample
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var pdfs = new List<PdfDocument>
{
PdfDocument.FromFile("file1.pdf"),
PdfDocument.FromFile("file2.pdf"),
PdfDocument.FromFile("file3.pdf")
};
var merged = PdfDocument.Merge(pdfs);
merged.SaveAs("merged.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System.Collections.Generic;
class IronPdfExample
{
static void Main()
{
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
var pdfs = new List<PdfDocument>
{
PdfDocument.FromFile("file1.pdf"),
PdfDocument.FromFile("file2.pdf"),
PdfDocument.FromFile("file3.pdf")
};
var merged = PdfDocument.Merge(pdfs);
merged.SaveAs("merged.pdf");
}
}
Imports IronPdf
Imports System.Collections.Generic
Class IronPdfExample
Shared Sub Main()
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim pdfs = New List(Of PdfDocument) From {
PdfDocument.FromFile("file1.pdf"),
PdfDocument.FromFile("file2.pdf"),
PdfDocument.FromFile("file3.pdf")
}
Dim merged = PdfDocument.Merge(pdfs)
merged.SaveAs("merged.pdf")
End Sub
End Class
The Ghostscript approach requires the full switch incantation (-dNOPAUSE, -dBATCH, -sDEVICE=pdfwrite) and concatenating file paths into a string array. IronPDF's static Merge method takes a typed IEnumerable<PdfDocument> and returns a new PdfDocument. Learn more about merging and splitting PDFs.
Critical Migration Notes
Page Indexing Conversion
One of the most important differences in this migration is page indexing. Ghostscript switches like -dFirstPage=N / -dLastPage=M are 1-indexed; IronPDF's CopyPages is 0-indexed (standard .NET):
// Ghostscript: -dFirstPage=5 -dLastPage=8 (1-indexed, inclusive)
// IronPDF: 0-indexed page array
var extracted = pdf.CopyPages(new[] {4, 5, 6, 7});
extracted.SaveAs("pages_5_to_8.pdf");
// Ghostscript: -dFirstPage=5 -dLastPage=8 (1-indexed, inclusive)
// IronPDF: 0-indexed page array
var extracted = pdf.CopyPages(new[] {4, 5, 6, 7});
extracted.SaveAs("pages_5_to_8.pdf");
' Ghostscript: -dFirstPage=5 -dLastPage=8 (1-indexed, inclusive)
' IronPDF: 0-indexed page array
Dim extracted = pdf.CopyPages({4, 5, 6, 7})
extracted.SaveAs("pages_5_to_8.pdf")
AGPL-3.0 License Concerns
Both Ghostscript and the Ghostscript.NET wrapper are dual-licensed under AGPL-3.0 or a commercial license from Artifex. AGPL-3.0's network-copyleft clause typically requires releasing the corresponding source of the larger work — including for SaaS / network-accessible deployments — unless you hold an Artifex commercial license. Migrating PDF workloads to IronPDF removes that obligation for the parts that move; if you keep Ghostscript only for PostScript ingest, an Artifex commercial license covers that piece. (This is a general summary, not legal advice — consult counsel for your specific deployment.)
No External Binaries
IronPDF is distributed as a NuGet package. Remove these after migration:
gsdll32.dllandgsdll64.dllfiles- Ghostscript installation from servers
- PATH environment variable configurations
GhostscriptVersionInforeferences in code
PostScript Files
IronPDF doesn't handle PostScript (.ps) files directly. If your workflow requires PostScript processing, either:
- Convert PostScript to PDF using another tool before IronPDF processing
- Convert source content to HTML and use IronPDF's HTML rendering
Performance Considerations
No Process Spawning
Shelling out to gswin64c.exe (or P/Invoking gsdll64.dll) carries process and native-interop overhead per operation. IronPDF runs in-process as managed .NET code:
// Ghostscript: process or P/Invoke overhead per call
processor.Process(switches.ToArray());
// IronPDF: in-process method call
var merged = PdfDocument.Merge(pdfs);
// Ghostscript: process or P/Invoke overhead per call
processor.Process(switches.ToArray());
// IronPDF: in-process method call
var merged = PdfDocument.Merge(pdfs);
' Ghostscript: process or P/Invoke overhead per call
processor.Process(switches.ToArray())
' IronPDF: in-process method call
Dim merged = PdfDocument.Merge(pdfs)
Thread Safety
IronPDF supports concurrent use of ChromePdfRenderer and PdfDocument from multiple threads. See the IronPDF documentation for guidance on parallel rendering patterns.
Migration Checklist
Pre-Migration
- Inventory all Ghostscript usage in codebase
- Document current command-line switches used
- Identify any PostScript processing (needs special handling)
- Review AGPL-3.0 license compliance status
- Obtain IronPDF license key
- Create migration branch in version control
Code Migration
- Remove Ghostscript.NET NuGet package:
dotnet remove package Ghostscript.NET - Install IronPDF NuGet package:
dotnet add package IronPdf - Remove external Ghostscript binary dependencies
- Remove
GhostscriptVersionInfoand DLL references - Convert
GhostscriptProcessor.Process()to IronPDF methods - Convert
GhostscriptRasterizertopdf.RasterizeToImageFiles() - Replace command-line switches with API calls
- Update error handling from stderr parsing to exceptions
- Convert 1-indexed page numbers to 0-indexed
Testing
- Test PDF to image conversion
- Test PDF merging
- Test page extraction
- Test compression quality
- Test password protection
- Verify output quality matches expectations
- Performance benchmark critical paths
Deployment
- Remove Ghostscript from servers
- Remove PATH configuration
- Remove
gsdll*.dllfiles from deployments - Verify application works without Ghostscript installed
Post-Migration
- Cancel Artifex commercial license (if previously held and no longer needed)
- Update documentation
- Train team on IronPDF API
- Monitor production for any issues

