From a5912e16e10db201371ed4c0e3db5758d24b8215 Mon Sep 17 00:00:00 2001 From: MaksymTkachuk Date: Fri, 28 Aug 2026 18:21:20 +0200 Subject: [PATCH] Added the updates to support Office files. --- .gitignore | 1 + CHANGELOG.md | 7 + Description.md | 4 +- .../Ghostscript.NET.DisplayTest.csproj | 1 + ...stscript.NET.PDFA3Converter.Samples.csproj | 1 + .../Program.cs | 32 +- .../SamplePaths.cs | 60 +++ .../Samples/FacturXWithMustangSample.cs | 11 +- .../Samples/FacturXWithZUGFeRDcsharpSample.cs | 11 +- .../Ghostscript.NET.Samples.csproj | 3 + Ghostscript.NET.Samples/Program.cs | 42 +- Ghostscript.NET.Samples/SampleFiles.cs | 67 +++ .../Samples/OfficeSupportSample.cs | 136 ++++++ .../Samples/PipedOutputSample.cs | 7 +- .../Samples/SendToPrinterSample.cs | 13 +- .../Samples/ViewerSample.cs | 96 ++++- .../TestFiles/OfficeSample.doc | Bin 0 -> 98304 bytes .../TestFiles/OfficeSample.docx | Bin 0 -> 111303 bytes Ghostscript.NET.Viewer/FMain.cs | 4 +- .../GhostscriptPdlLibraryNotFoundException.cs | 59 +++ Ghostscript.NET/Ghostscript.NET.csproj | 4 +- Ghostscript.NET/GhostscriptLibrary.cs | 5 + Ghostscript.NET/GhostscriptNativeKind.cs | 47 +++ Ghostscript.NET/GhostscriptOffice.cs | 393 ++++++++++++++++++ Ghostscript.NET/GhostscriptPipedOutput.cs | 13 +- Ghostscript.NET/GhostscriptVersionInfo.cs | 298 ++++++++++++- .../CrossPlatformNativeLibraryHelper.cs | 57 +++ Ghostscript.NET/Helpers/StreamHelper.cs | 8 +- .../Interop/DynamicNativeLibrary.cs | 50 +++ .../OutputDevices/GhostscriptDevice.cs | 6 + .../PDFA3Converter/PDFA3Converter.cs | 43 +- .../Processor/GhostscriptProcessor.cs | 33 ++ .../Rasterizer/GhostscriptRasterizer.cs | 4 +- Ghostscript.NET/Viewer/GhostscriptViewer.cs | 23 +- README.md | 71 +++- Versions.props | 2 +- 36 files changed, 1524 insertions(+), 88 deletions(-) create mode 100644 Ghostscript.NET.PDFA3Converter.Samples/SamplePaths.cs create mode 100644 Ghostscript.NET.Samples/SampleFiles.cs create mode 100644 Ghostscript.NET.Samples/Samples/OfficeSupportSample.cs create mode 100644 Ghostscript.NET.Samples/TestFiles/OfficeSample.doc create mode 100644 Ghostscript.NET.Samples/TestFiles/OfficeSample.docx create mode 100644 Ghostscript.NET/Exceptions/GhostscriptPdlLibraryNotFoundException.cs create mode 100644 Ghostscript.NET/GhostscriptNativeKind.cs create mode 100644 Ghostscript.NET/GhostscriptOffice.cs diff --git a/.gitignore b/.gitignore index c0901e9..57060b8 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ x64/ build/ [Bb]in/ [Oo]bj/ +[Oo]utput/ # MSTest test Results [Tt]est[Rr]esult*/ diff --git a/CHANGELOG.md b/CHANGELOG.md index b56bd29..e92ccc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [1.3.5] - 2026-08-28 + +- **Office files:** Word, Excel, and PowerPoint can be converted and rasterized when a licensed GhostPDL library is present. Without it, Office APIs throw `GhostscriptPdlLibraryNotFoundException` and point users to Artifex for a commercial Ghostscript.NET license. +- **Existing processor code:** `GhostscriptProcessor` detects an Office path in the argument list, loads `gpdldll` if it is on the search path, and treats `-dSAFER` as `-dNOSAFER` for that job. Callers can keep `GetLastInstalledVersion()`. +- **32-bit GhostPDL:** `gpdldll32.dll` exports stdcall names (`_gsapi_revision@8`). Ghostscript.NET now resolves those in x86 processes. NativeAssets `gsdll32.dll` already used undecorated names, so it was unaffected. +- GhostPDL/SmartOffice is **commercial**. It is not in `Ghostscript.NativeAssets` or on nuget.org. Licensed users copy the library from Ghostscript.NET.Office into their project. + ### [1.3.4] - 2026-07-20 - **Bundled native library discovery:** `GhostscriptVersionInfo` can locate app-local Ghostscript binaries (for example from `Ghostscript.NativeAssets`) via `TryGetBundledVersion`, `GetBundledVersion`, and `GetPreferredVersion`. `GetLastInstalledVersion` now prefers bundled assets before falling back to a system installation. diff --git a/Description.md b/Description.md index d54bed1..173a9ce 100644 --- a/Description.md +++ b/Description.md @@ -1,6 +1,6 @@ -**Ghostscript.NET** is the most completed managed wrapper library around the [Ghostscript](https://ghostscript.com) library - an interpreter for PDF and PostScript files. +**Ghostscript.NET** is the most completed managed wrapper library around the [Ghostscript](https://ghostscript.com) library - an interpreter for PDF and PostScript files. With a licensed GhostPDL library (`gpdldll` / `libgpdl`) it also converts Microsoft Office documents. -Ghostscript can be provided via a system install or the optional `Ghostscript.NativeAssets` NuGet package (app-local binaries). +Ghostscript can be provided via a system install or the optional `Ghostscript.NativeAssets` NuGet package (app-local binaries). Office/SmartOffice natives are **not** in that package; licensed users obtain them from Ghostscript.NET.Office. ### Features diff --git a/Ghostscript.NET.DisplayTest/Ghostscript.NET.DisplayTest.csproj b/Ghostscript.NET.DisplayTest/Ghostscript.NET.DisplayTest.csproj index 23db73f..b25be71 100644 --- a/Ghostscript.NET.DisplayTest/Ghostscript.NET.DisplayTest.csproj +++ b/Ghostscript.NET.DisplayTest/Ghostscript.NET.DisplayTest.csproj @@ -36,6 +36,7 @@ + diff --git a/Ghostscript.NET.PDFA3Converter.Samples/Ghostscript.NET.PDFA3Converter.Samples.csproj b/Ghostscript.NET.PDFA3Converter.Samples/Ghostscript.NET.PDFA3Converter.Samples.csproj index 5245519..1239c47 100644 --- a/Ghostscript.NET.PDFA3Converter.Samples/Ghostscript.NET.PDFA3Converter.Samples.csproj +++ b/Ghostscript.NET.PDFA3Converter.Samples/Ghostscript.NET.PDFA3Converter.Samples.csproj @@ -9,6 +9,7 @@ + diff --git a/Ghostscript.NET.PDFA3Converter.Samples/Program.cs b/Ghostscript.NET.PDFA3Converter.Samples/Program.cs index 949c523..597837e 100644 --- a/Ghostscript.NET.PDFA3Converter.Samples/Program.cs +++ b/Ghostscript.NET.PDFA3Converter.Samples/Program.cs @@ -34,18 +34,36 @@ static void Main(string[] args) if (!GhostscriptVersionInfo.IsGhostscriptInstalled) { - throw new Exception("You don't have Ghostscript installed on this machine!"); + throw new Exception("Ghostscript was not found. Install Ghostscript or reference Ghostscript.NativeAssets."); } - ISample sample; + Console.WriteLine("Using Ghostscript: " + SamplePaths.ResolveGhostscriptDll()); - sample = new FacturXWithMustangSample(); - sample.Start(); + int failed = 0; + ISample[] samples = + { + new FacturXWithMustangSample(), + new FacturXWithZUGFeRDcsharpSample() + }; - sample = new FacturXWithZUGFeRDcsharpSample(); - sample.Start(); + foreach (ISample sample in samples) + { + string name = sample.GetType().Name; + try + { + sample.Start(); + Console.WriteLine(name + " completed."); + } + catch (Exception ex) + { + failed++; + Console.WriteLine(name + " failed: " + ex.Message); + } + } - Console.ReadLine(); + Console.WriteLine(failed == 0 + ? "PDFA3Converter samples completed." + : failed + " sample(s) failed."); } } } diff --git a/Ghostscript.NET.PDFA3Converter.Samples/SamplePaths.cs b/Ghostscript.NET.PDFA3Converter.Samples/SamplePaths.cs new file mode 100644 index 0000000..03ac553 --- /dev/null +++ b/Ghostscript.NET.PDFA3Converter.Samples/SamplePaths.cs @@ -0,0 +1,60 @@ +// Copyright (C) 2024 Artifex Software, Inc. +// +// This file is part of Ghostscript.NET. +// +// Ghostscript.NET is free software: you can redistribute it and/or modify it +// under the terms of the GNU Affero General Public License as published by the +// Free Software Foundation, either version 3 of the License, or (at your option) +// any later version. +// +// Ghostscript.NET is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +// details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Ghostscript.NET. If not, see +// +// Alternative licensing terms are available from the licensor. +// For commercial licensing, see or contact +// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, +// CA 94129, USA, for further information. + +using System; +using System.IO; + +namespace Ghostscript.NET.PDFA3Converter.Samples +{ + internal static class SamplePaths + { + public static string ResolveGhostscriptDll() + { + GhostscriptVersionInfo version = GhostscriptVersionInfo.GetPreferredVersion(); + return version.DllPath; + } + + public static string GetBlankPdf() + { + string[] candidates = + { + Path.Combine(AppContext.BaseDirectory, "Samples", "blank.pdf"), + Path.GetFullPath(Path.Combine("Samples", "blank.pdf")) + }; + + foreach (string candidate in candidates) + { + if (File.Exists(candidate)) + { + return candidate; + } + } + + throw new FileNotFoundException("Could not find Samples/blank.pdf."); + } + + public static string GetOutputPath(string fileName) + { + return Path.Combine(AppContext.BaseDirectory, fileName); + } + } +} diff --git a/Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithMustangSample.cs b/Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithMustangSample.cs index 92f3b3b..765f05f 100644 --- a/Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithMustangSample.cs +++ b/Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithMustangSample.cs @@ -46,12 +46,11 @@ public void Start() zf2p.generateXML(i); System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); - string outfilename = "my-factur-x-mustang-sample.xml"; + string outfilename = SamplePaths.GetOutputPath("my-factur-x-mustang-sample.xml"); File.WriteAllBytes(outfilename, zf2p.getXML()); - string gsFilePath = @"C:\Program Files\gs\gs10.06.0\bin\gsdll64.dll"; - Console.WriteLine("Using Ghostscript filepath: " + gsFilePath); - Console.WriteLine("Ensure this is the filepath to your installed Ghostscript!"); + string gsFilePath = SamplePaths.ResolveGhostscriptDll(); + Console.WriteLine("Using Ghostscript: " + gsFilePath); PDFA3Converter converter = new PDFA3Converter(gsFilePath); @@ -59,7 +58,9 @@ public void Start() converter.SetZUGFeRDVersion("2.3"); converter.SetEmbeddedXMLFile(outfilename); - converter.ConvertToPDFA3(@"Samples/blank.pdf", @"sample-invoice-mustang.pdf"); + string outputPdf = SamplePaths.GetOutputPath("sample-invoice-mustang.pdf"); + converter.ConvertToPDFA3(SamplePaths.GetBlankPdf(), outputPdf); + Console.WriteLine("Wrote " + outputPdf); System.IO.File.Delete(outfilename); } } diff --git a/Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithZUGFeRDcsharpSample.cs b/Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithZUGFeRDcsharpSample.cs index fa59744..ddc7c84 100644 --- a/Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithZUGFeRDcsharpSample.cs +++ b/Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithZUGFeRDcsharpSample.cs @@ -38,18 +38,19 @@ public void Start() { Console.WriteLine(Environment.NewLine); Console.WriteLine("Running FacturXWithZUGFeRDcsharpSample"); - string outFilename = "my-factur-x-zugferd-sample.xml"; + string outFilename = SamplePaths.GetOutputPath("my-factur-x-zugferd-sample.xml"); InvoiceDescriptor invoice = CreateInvoice(); invoice.Save(outFilename, ZUGFeRDVersion.Version22, s2industries.ZUGFeRD.Profile.Comfort); - string gsFilePath = @"C:\Program Files\gs\gs10.06.0\bin\gsdll64.dll"; - Console.WriteLine("Using Ghostscript filepath: "+ gsFilePath); - Console.WriteLine("Ensure this is the filepath to your installed Ghostscript!"); + string gsFilePath = SamplePaths.ResolveGhostscriptDll(); + Console.WriteLine("Using Ghostscript: " + gsFilePath); PDFA3Converter converter = new PDFA3Converter(gsFilePath); converter.SetZUGFeRDProfile("EN 16931"); converter.SetZUGFeRDVersion("2.3"); converter.SetEmbeddedXMLFile(outFilename); - converter.ConvertToPDFA3(@"Samples/blank.pdf", @"sample-invoice-zugferd.pdf"); + string outputPdf = SamplePaths.GetOutputPath("sample-invoice-zugferd.pdf"); + converter.ConvertToPDFA3(SamplePaths.GetBlankPdf(), outputPdf); + Console.WriteLine("Wrote " + outputPdf); System.IO.File.Delete(outFilename); } diff --git a/Ghostscript.NET.Samples/Ghostscript.NET.Samples.csproj b/Ghostscript.NET.Samples/Ghostscript.NET.Samples.csproj index 995d49b..da51195 100644 --- a/Ghostscript.NET.Samples/Ghostscript.NET.Samples.csproj +++ b/Ghostscript.NET.Samples/Ghostscript.NET.Samples.csproj @@ -32,6 +32,9 @@ + + + diff --git a/Ghostscript.NET.Samples/Program.cs b/Ghostscript.NET.Samples/Program.cs index a438eb3..5f3c997 100644 --- a/Ghostscript.NET.Samples/Program.cs +++ b/Ghostscript.NET.Samples/Program.cs @@ -25,24 +25,20 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using Ghostscript.NET; -using Ghostscript.NET.Processor; -using Ghostscript.NET.Rasterizer; using Ghostscript.NET.Samples; -using javax.print.attribute.standard; -using SkiaSharp; -using SixLabors.ImageSharp; using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; Console.WriteLine("Ghostscript.NET Samples"); if (!GhostscriptVersionInfo.IsGhostscriptInstalled) { - throw new Exception("You don't have Ghostscript installed on this machine!"); + throw new Exception("Ghostscript was not found. Install Ghostscript or reference Ghostscript.NativeAssets."); } +Console.WriteLine("Using Ghostscript: " + GhostscriptVersionInfo.GetPreferredVersion().DllPath); + List samples = new() { new GetInkCoverageSample(), @@ -57,18 +53,34 @@ new DeviceUsageSample(), new PipedOutputSample(), new SendToPrinterSample(), - new UnicodeTestSample() + new UnicodeTestSample(), + new OfficeSupportSample() }; +string outputDir = SampleFiles.OutputDirectory; +Directory.CreateDirectory(outputDir); +Directory.CreateDirectory("Output"); + +int failed = 0; foreach (ISample sample in samples) { - string path = @"Output"; - - if (!Directory.Exists(path)) + string name = sample.GetType().Name; + Console.WriteLine(); + Console.WriteLine("--- " + name + " ---"); + try { - Directory.CreateDirectory(path); + sample.Start(); + Console.WriteLine("Sample '" + name + "' completed."); } + catch (Exception ex) + { + failed++; + Console.WriteLine("Sample '" + name + "' failed: " + ex.Message); + } +} - sample.Start(); - Console.WriteLine($"Sample '{sample.GetType().Name}' run successful!"); -} \ No newline at end of file +Console.WriteLine(); +Console.WriteLine(failed == 0 + ? "All samples completed. Exiting." + : failed + " sample(s) failed. Exiting."); +Environment.Exit(failed == 0 ? 0 : 1); diff --git a/Ghostscript.NET.Samples/SampleFiles.cs b/Ghostscript.NET.Samples/SampleFiles.cs new file mode 100644 index 0000000..10b35f3 --- /dev/null +++ b/Ghostscript.NET.Samples/SampleFiles.cs @@ -0,0 +1,67 @@ +// +// SampleFiles.cs +// This file is part of Ghostscript.NET.Samples project +// +// Author: Artifex Software Inc. +// Copyright (c) 2026 by Artifex Software Inc. All rights reserved. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace Ghostscript.NET.Samples +{ + internal static class SampleFiles + { + public static string Get(string fileName) + { + string path; + if (TryGet(fileName, out path)) + { + return path; + } + + throw new FileNotFoundException("Sample file not found: " + fileName); + } + + public static bool TryGet(string fileName, out string path) + { + path = null; + + foreach (string directory in GetSearchDirectories()) + { + string candidate = Path.Combine(directory, fileName); + if (File.Exists(candidate)) + { + path = Path.GetFullPath(candidate); + return true; + } + } + + return false; + } + + public static string OutputDirectory + { + get + { + string directory = Path.Combine(AppContext.BaseDirectory, "Output"); + Directory.CreateDirectory(directory); + return directory; + } + } + + private static IEnumerable GetSearchDirectories() + { + yield return Path.Combine(AppContext.BaseDirectory, "TestFiles"); + yield return Path.GetFullPath("TestFiles"); + + string directory = AppContext.BaseDirectory; + for (int i = 0; i < 6 && !string.IsNullOrEmpty(directory); i++) + { + yield return Path.Combine(directory, "TestFiles"); + directory = Path.GetDirectoryName(directory); + } + } + } +} diff --git a/Ghostscript.NET.Samples/Samples/OfficeSupportSample.cs b/Ghostscript.NET.Samples/Samples/OfficeSupportSample.cs new file mode 100644 index 0000000..3e1ed18 --- /dev/null +++ b/Ghostscript.NET.Samples/Samples/OfficeSupportSample.cs @@ -0,0 +1,136 @@ +// +// OfficeSupportSample.cs +// This file is part of Ghostscript.NET.Samples project +// +// Author: Artifex Software Inc. +// Copyright (c) 2026 by Artifex Software Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.IO; +using Ghostscript.NET.Processor; +using Ghostscript.NET.Rasterizer; +using SkiaSharp; + +namespace Ghostscript.NET.Samples +{ + /// + /// Office files require a licensed GhostPDL library (gpdldll64.dll / libgpdl.so), + /// not standard Ghostscript. Place the DLL from Ghostscript.NET.Office in the app folder + /// or set GHOSTPDL_DLL. + /// + public class OfficeSupportSample : ISample + { + public void Start() + { + GhostscriptVersionInfo pdl; + if (!GhostscriptVersionInfo.TryGetGhostPdlVersion(out pdl)) + { + Console.WriteLine(GhostscriptOffice.CommercialLicenseRequiredMessage); + Console.WriteLine("Skipping OfficeSupportSample: no licensed GhostPDL library was found."); + return; + } + + string inputPath = FindSampleOfficeFile(); + if (inputPath == null) + { + Console.WriteLine("Skipping OfficeSupportSample: no .doc/.docx test file found."); + return; + } + + Console.WriteLine("Using GhostPDL: " + pdl.DllPath); + Console.WriteLine("Input: " + inputPath); + + string outputDir = Path.GetFullPath("Output"); + Directory.CreateDirectory(outputDir); + + string pdfPath = Path.Combine(outputDir, "OfficeSupportSample.pdf"); + GhostscriptOffice.ConvertToPdf(inputPath, pdfPath, pdl); + Console.WriteLine("PDF: " + pdfPath); + + using (GhostscriptProcessor processor = GhostscriptProcessor.CreateForInput(inputPath)) + { + processor.Process(new[] + { + "-ghostscript.net", + "-dNOPAUSE", + "-dBATCH", + "-sDEVICE=png16m", + "-r96", + "-sOutputFile=" + Path.Combine(outputDir, "OfficeSupportSample-%03d.png"), + "-f", + Path.GetFullPath(inputPath) + }); + } + + using (GhostscriptRasterizer rasterizer = new GhostscriptRasterizer()) + { + rasterizer.Open(inputPath); + Console.WriteLine("Page count: " + rasterizer.PageCount); + + if (rasterizer.PageCount > 0) + { + SKBitmap page = rasterizer.GetPage(96, 1); + if (page != null) + { + string pngPath = Path.Combine(outputDir, "OfficeSupportSample-rasterizer.png"); + using (SKImage image = SKImage.FromBitmap(page)) + using (SKData data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (FileStream stream = File.OpenWrite(pngPath)) + { + data.SaveTo(stream); + } + + Console.WriteLine("Rasterizer page 1: " + pngPath); + } + } + } + } + + private static string FindSampleOfficeFile() + { + string[] names = { "OfficeSample.doc", "OfficeSample.docx" }; + string dir = AppContext.BaseDirectory; + + for (int i = 0; i < 8 && !string.IsNullOrEmpty(dir); i++) + { + foreach (string name in names) + { + string candidate = Path.Combine(dir, "TestFiles", name); + if (File.Exists(candidate)) + { + return candidate; + } + + candidate = Path.Combine(dir, name); + if (File.Exists(candidate)) + { + return candidate; + } + } + + dir = Path.GetDirectoryName(dir); + } + + return null; + } + } +} diff --git a/Ghostscript.NET.Samples/Samples/PipedOutputSample.cs b/Ghostscript.NET.Samples/Samples/PipedOutputSample.cs index 4ca8a29..f529459 100644 --- a/Ghostscript.NET.Samples/Samples/PipedOutputSample.cs +++ b/Ghostscript.NET.Samples/Samples/PipedOutputSample.cs @@ -42,7 +42,9 @@ public class PipedOutputSample : ISample { public void Start() { - string inputFile = @"..\..\..\TestFiles\PipedOutputSample.ps"; + string inputFile = SampleFiles.TryGet("PipedOutputSample.ps", out string ps) + ? ps + : @"..\..\..\TestFiles\PipedOutputSample.ps"; GhostscriptPipedOutput gsPipedOutput = new GhostscriptPipedOutput(); @@ -76,7 +78,8 @@ public void Start() //} //else if (writeToDisk) //{ - File.WriteAllBytes(@".\output\PipedOutputSample.pdf", rawDocumentData); + Directory.CreateDirectory(SampleFiles.OutputDirectory); + File.WriteAllBytes(Path.Combine(SampleFiles.OutputDirectory, "PipedOutputSample.pdf"), rawDocumentData); //} } catch (Exception ex) diff --git a/Ghostscript.NET.Samples/Samples/SendToPrinterSample.cs b/Ghostscript.NET.Samples/Samples/SendToPrinterSample.cs index 190d1d6..b2ff9d8 100644 --- a/Ghostscript.NET.Samples/Samples/SendToPrinterSample.cs +++ b/Ghostscript.NET.Samples/Samples/SendToPrinterSample.cs @@ -34,10 +34,19 @@ public class SendToPrinterSample : ISample { public void Start() { - // YOU NEED TO HAVE ADMINISTRATOR RIGHTS TO RUN THIS CODE + // mswinpr2 + "Microsoft Print to PDF" opens a Save dialog and never returns, + // which keeps Ghostscript.NET.Samples from exiting. + string runPrinter = Environment.GetEnvironmentVariable("GHOSTSCRIPT_NET_RUN_PRINTER"); + if (!string.Equals(runPrinter, "1", StringComparison.OrdinalIgnoreCase)) + { + Console.WriteLine("Skipping SendToPrinterSample (would wait on a printer/save dialog). Set GHOSTSCRIPT_NET_RUN_PRINTER=1 to run it."); + return; + } string printerName = "Microsoft Print to PDF"; - string inputFile = @"..\..\..\TestFiles\SendToPrinterSample.pdf"; + string inputFile = SampleFiles.TryGet("SendToPrinterSample.pdf", out string pdf) + ? pdf + : @"..\..\..\TestFiles\SendToPrinterSample.pdf"; using (GhostscriptProcessor processor = new GhostscriptProcessor()) { diff --git a/Ghostscript.NET.Samples/Samples/ViewerSample.cs b/Ghostscript.NET.Samples/Samples/ViewerSample.cs index 845bad0..f07d942 100644 --- a/Ghostscript.NET.Samples/Samples/ViewerSample.cs +++ b/Ghostscript.NET.Samples/Samples/ViewerSample.cs @@ -25,12 +25,14 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.IO; using System.Threading; using SkiaSharp; // required Ghostscript.NET namespaces using Ghostscript.NET; +using Ghostscript.NET.Processor; using Ghostscript.NET.Viewer; namespace Ghostscript.NET.Samples @@ -58,8 +60,11 @@ public void Start() GhostscriptVersionInfo.GetLastInstalledVersion(); _firstPageDone = new ManualResetEventSlim(false); + bool pageReady = false; try { + string inputPath = PrepareViewerInput(); + // create a new instance of the viewer _viewer = new GhostscriptViewer(); @@ -74,23 +79,56 @@ public void Start() _viewer.DisplayUpdate += new GhostscriptViewerViewEventHandler(_viewer_DisplayUpdate); _viewer.DisplayPage += new GhostscriptViewerViewEventHandler(_viewer_DisplayPage); - // Use TestFiles\PipedOutputSample.ps (included). For PDF, place e.g. - // ProcessorSample1.pdf in TestFiles and change the path below. - // If you want to use multiple viewers within a single process then pass - // true as the last parameter so Ghostscript loads from memory. + // Open a PDF. Opening PipedOutputSample.ps directly with GhostscriptViewer + // can block forever inside gsapi_run_string (DisplaySize fires, DisplayPage does not). Console.WriteLine("Rendering first page to Output\\ViewerSample.png ..."); - _viewer.Open(@"..\..\..\TestFiles\PipedOutputSample.ps", _lastInstalledVersion, false); - if (!_firstPageDone.Wait(TimeSpan.FromSeconds(120))) + // Open on a background thread so a stuck gsapi call cannot freeze the sample runner. + Exception openError = null; + Thread openThread = new Thread(() => + { + try + { + _viewer.Open(inputPath, _lastInstalledVersion, false); + } + catch (Exception ex) + { + openError = ex; + try { _firstPageDone?.Set(); } catch { } + } + }); + openThread.IsBackground = true; + openThread.Name = "GhostscriptViewer.Open"; + openThread.Start(); + + pageReady = _firstPageDone.Wait(TimeSpan.FromSeconds(30)); + if (!pageReady) { Console.WriteLine("Timed out waiting for the first page (check Ghostscript and the input file)."); } + + if (openError != null) + { + throw openError; + } } finally { - if (_viewer != null) + if (pageReady && _viewer != null) + { + try + { + _viewer.Dispose(); + } + catch (Exception ex) + { + Console.WriteLine("Viewer dispose: " + ex.Message); + } + + _viewer = null; + } + else { - _viewer.Dispose(); _viewer = null; } @@ -146,8 +184,8 @@ void _viewer_DisplayPage(object sender, GhostscriptViewerViewEventArgs e) return; } - Directory.CreateDirectory("Output"); - string outPath = Path.Combine("Output", "ViewerSample.png"); + Directory.CreateDirectory(SampleFiles.OutputDirectory); + string outPath = Path.Combine(SampleFiles.OutputDirectory, "ViewerSample.png"); using (SKImage image = SKImage.FromBitmap(bmp)) using (SKData data = image.Encode(SKEncodedImageFormat.Png, 100)) using (Stream stream = File.Create(outPath)) @@ -167,6 +205,44 @@ void _viewer_DisplayPage(object sender, GhostscriptViewerViewEventArgs e) } } + private static string PrepareViewerInput() + { + string pdfPath; + if (SampleFiles.TryGet("ViewerSample.pdf", out pdfPath)) + { + return pdfPath; + } + + if (SampleFiles.TryGet("ProcessorSample1.pdf", out pdfPath)) + { + return pdfPath; + } + + string psPath; + if (!SampleFiles.TryGet("PipedOutputSample.ps", out psPath)) + { + throw new FileNotFoundException("No viewer sample input file was found."); + } + + string outputPdf = Path.Combine(SampleFiles.OutputDirectory, "ViewerSample-input.pdf"); + using (GhostscriptProcessor processor = new GhostscriptProcessor()) + { + processor.Process(new[] + { + "-dBATCH", + "-dNOPAUSE", + "-dNOPROMPT", + "-dNOSAFER", + "-sDEVICE=pdfwrite", + "-sOutputFile=" + outputPdf, + "-f", + psPath + }); + } + + return outputPdf; + } + // dummy method just to list other viewer properties and methods private void Other_Viewer_Methods() { diff --git a/Ghostscript.NET.Samples/TestFiles/OfficeSample.doc b/Ghostscript.NET.Samples/TestFiles/OfficeSample.doc new file mode 100644 index 0000000000000000000000000000000000000000..b3a82c003379ab1fbd42db969e8c8e96bf699b0d GIT binary patch literal 98304 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 literal 0 HcmV?d00001 diff --git a/Ghostscript.NET.Samples/TestFiles/OfficeSample.docx b/Ghostscript.NET.Samples/TestFiles/OfficeSample.docx new file mode 100644 index 0000000000000000000000000000000000000000..365b8e19ca5cc76c49133385df59bdd39a9fe15e GIT binary patch literal 111303 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

=b48lOfQl10$YNh^@yTI|+SV?g&r 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 S1Ox~8fB{;*ss_+~fc_6Y#^06z literal 0 HcmV?d00001 diff --git a/Ghostscript.NET.Viewer/FMain.cs b/Ghostscript.NET.Viewer/FMain.cs index 9b1aa02..bec8623 100644 --- a/Ghostscript.NET.Viewer/FMain.cs +++ b/Ghostscript.NET.Viewer/FMain.cs @@ -147,8 +147,8 @@ private void FMain_Load(object sender, EventArgs e) private void mnuFileOpen_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); - ofd.Title = "Open PDF file"; - ofd.Filter = "PDF, PS, EPS files|*.pdf;*.ps;*.eps"; + ofd.Title = "Open document"; + ofd.Filter = "Documents|*.pdf;*.ps;*.eps;*.doc;*.docx;*.xls;*.xlsx;*.ppt;*.pptx;*.odt;*.ods;*.odp;*.rtf|PDF, PS, EPS files|*.pdf;*.ps;*.eps|Office files|*.doc;*.docx;*.xls;*.xlsx;*.ppt;*.pptx;*.odt;*.ods;*.odp;*.rtf|All files|*.*"; if (ofd.ShowDialog(this) == System.Windows.Forms.DialogResult.OK) { diff --git a/Ghostscript.NET/Exceptions/GhostscriptPdlLibraryNotFoundException.cs b/Ghostscript.NET/Exceptions/GhostscriptPdlLibraryNotFoundException.cs new file mode 100644 index 0000000..340f542 --- /dev/null +++ b/Ghostscript.NET/Exceptions/GhostscriptPdlLibraryNotFoundException.cs @@ -0,0 +1,59 @@ +// +// GhostscriptPdlLibraryNotFoundException.cs +// This file is part of Ghostscript.NET library +// +// Author: Artifex Software Inc. +// Copyright (c) 2026 by Artifex Software Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; + +namespace Ghostscript.NET +{ + ///

+ /// Thrown when an Office file is processed but no GhostPDL native library was found. + /// + public class GhostscriptPdlLibraryNotFoundException : GhostscriptException + { + /// + /// Creates an exception describing how to locate GhostPDL. + /// + public GhostscriptPdlLibraryNotFoundException() + : base(BuildMessage(), -1002) { } + + /// + /// Creates an exception with a custom message. + /// + public GhostscriptPdlLibraryNotFoundException(string message) + : base(message, -1002) { } + + private static string BuildMessage() + { + string bitness = Environment.Is64BitProcess ? "64-bit" : "32-bit"; + string dllName = Environment.Is64BitProcess ? "gpdldll64.dll" : "gpdldll32.dll"; + return + GhostscriptOffice.CommercialLicenseRequiredMessage + + " If you already have that license, copy the " + bitness + " GhostPDL library (" + dllName + ") " + + "from Ghostscript.NET.Office into your application folder, set GHOSTPDL_DLL to its full path, " + + "or pass a GhostscriptVersionInfo that points at GhostPDL."; + } + } +} diff --git a/Ghostscript.NET/Ghostscript.NET.csproj b/Ghostscript.NET/Ghostscript.NET.csproj index cde28fc..e747841 100644 --- a/Ghostscript.NET/Ghostscript.NET.csproj +++ b/Ghostscript.NET/Ghostscript.NET.csproj @@ -9,10 +9,10 @@ $(GhostscriptNetVersion) A C# binding for Ghostscript library Description.md - C#;F#;VB.Net;Ghostscript;DotNet;PDF + C#;F#;VB.Net;Ghostscript;DotNet;PDF;Office;DOCX True gs-icon.png - Adds bundled native-library discovery and the optional Ghostscript.NativeAssets companion package. + Adds Microsoft Office support when a licensed GhostPDL (SmartOffice) native library is placed in the application. diff --git a/Ghostscript.NET/GhostscriptLibrary.cs b/Ghostscript.NET/GhostscriptLibrary.cs index 6ed894c..788568e 100644 --- a/Ghostscript.NET/GhostscriptLibrary.cs +++ b/Ghostscript.NET/GhostscriptLibrary.cs @@ -49,6 +49,11 @@ public class GhostscriptLibrary : IDisposable #endregion + internal GhostscriptVersionInfo VersionInfo + { + get { return _version; } + } + #region Constructor - buffer /// diff --git a/Ghostscript.NET/GhostscriptNativeKind.cs b/Ghostscript.NET/GhostscriptNativeKind.cs new file mode 100644 index 0000000..cce82c4 --- /dev/null +++ b/Ghostscript.NET/GhostscriptNativeKind.cs @@ -0,0 +1,47 @@ +// +// GhostscriptNativeKind.cs +// This file is part of Ghostscript.NET library +// +// Author: Artifex Software Inc. +// Copyright (c) 2026 by Artifex Software Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +namespace Ghostscript.NET +{ + /// + /// Identifies which native interpreter a loaded library is. + /// + public enum GhostscriptNativeKind + { + /// + /// Standard Ghostscript library (gsdll64.dll / libgs.so). + /// PDF, PostScript, and EPS only. + /// + Ghostscript = 0, + + /// + /// GhostPDL library (gpdldll64.dll / libgpdl.so). + /// Same gsapi_* surface as Ghostscript, plus Office (SmartOffice), + /// PCL, XPS, and additional image languages. + /// + GhostPdl = 1 + } +} diff --git a/Ghostscript.NET/GhostscriptOffice.cs b/Ghostscript.NET/GhostscriptOffice.cs new file mode 100644 index 0000000..0ba9938 --- /dev/null +++ b/Ghostscript.NET/GhostscriptOffice.cs @@ -0,0 +1,393 @@ +// +// GhostscriptOffice.cs +// This file is part of Ghostscript.NET library +// +// Author: Artifex Software Inc. +// Copyright (c) 2026 by Artifex Software Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Ghostscript.NET.Processor; + +namespace Ghostscript.NET +{ + /// + /// Microsoft Office / OpenDocument support via GhostPDL (SmartOffice). + /// Ghostscript itself cannot open these files; GhostPDL converts them + /// internally (Office → PDF) then runs the Ghostscript pipeline. + /// + public static class GhostscriptOffice + { + /// + /// Artifex contact page for a commercial Ghostscript.NET license (Office / SmartOffice). + /// + public const string CommercialLicenseUrl = "https://artifex.com/contact/ghostscript"; + + /// + /// Message shown when Office files are used without a commercial Ghostscript.NET license + /// (no SmartOffice-enabled GhostPDL library). + /// + public static string CommercialLicenseRequiredMessage + { + get + { + return + "Microsoft Office files are a commercial Ghostscript.NET feature and are not included in the open-source (AGPL) package. " + + "To convert Word, Excel, PowerPoint, and related files, obtain a commercial Ghostscript.NET license from Artifex: " + + CommercialLicenseUrl + " " + + "Licensed customers receive the SmartOffice-enabled GhostPDL native library (Ghostscript.NET.Office)."; + } + } + + /// + /// Filename extensions handled by the GhostPDL SmartOffice language. + /// + public static readonly string[] SupportedExtensions = new[] + { + ".doc", ".docx", + ".xls", ".xlsx", + ".ppt", ".pptx", + ".odt", ".ods", ".odp", + ".rtf", ".csv", + ".hwp", ".hwpx" + }; + + /// + /// Returns true when has an Office / OpenDocument extension. + /// + public static bool IsOfficeFile(string path) + { + if (string.IsNullOrWhiteSpace(path)) + { + return false; + } + + return IsOfficeExtension(Path.GetExtension(path)); + } + + /// + /// Returns true when is a supported Office extension. + /// + public static bool IsOfficeExtension(string extension) + { + if (string.IsNullOrWhiteSpace(extension)) + { + return false; + } + + if (extension[0] != '.') + { + extension = "." + extension; + } + + for (int i = 0; i < SupportedExtensions.Length; i++) + { + if (string.Equals(SupportedExtensions[i], extension, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + + /// + /// Returns true when any path in is an Office file. + /// + public static bool ContainsOfficeFile(IEnumerable paths) + { + if (paths == null) + { + return false; + } + + foreach (string path in paths) + { + if (IsOfficeFile(path)) + { + return true; + } + } + + return false; + } + + /// + /// Rewrites processor arguments so existing Ghostscript samples can open Office files: + /// full paths, and -dSAFER replaced with -dNOSAFER (SmartOffice must read the input). + /// + internal static string[] PrepareProcessorArgs(string[] args) + { + List result = new List(args.Length + 1); + bool hasNoSafer = false; + + for (int i = 0; i < args.Length; i++) + { + string arg = args[i]; + + if (IsSaferSwitch(arg)) + { + if (!hasNoSafer) + { + result.Add("-dNOSAFER"); + hasNoSafer = true; + } + continue; + } + + if (IsNoSaferSwitch(arg)) + { + if (!hasNoSafer) + { + result.Add("-dNOSAFER"); + hasNoSafer = true; + } + continue; + } + + if (IsOfficeFile(arg)) + { + result.Add(TryGetFullPath(arg)); + continue; + } + + if (arg != null && arg.StartsWith("-sOutputFile=", StringComparison.OrdinalIgnoreCase)) + { + string path = arg.Substring("-sOutputFile=".Length); + result.Add("-sOutputFile=" + TryGetFullPath(path)); + continue; + } + + result.Add(arg); + } + + if (!hasNoSafer) + { + int insertAt = result.Count > 0 ? 1 : 0; + result.Insert(insertAt, "-dNOSAFER"); + } + + return result.ToArray(); + } + + private static bool IsSaferSwitch(string arg) + { + if (string.IsNullOrEmpty(arg)) + { + return false; + } + + return string.Equals(arg, "-dSAFER", StringComparison.OrdinalIgnoreCase) + || arg.StartsWith("-dSAFER=", StringComparison.OrdinalIgnoreCase); + } + + private static bool IsNoSaferSwitch(string arg) + { + return !string.IsNullOrEmpty(arg) + && string.Equals(arg, "-dNOSAFER", StringComparison.OrdinalIgnoreCase); + } + + private static string TryGetFullPath(string path) + { + if (string.IsNullOrWhiteSpace(path)) + { + return path; + } + + try + { + return Path.GetFullPath(path); + } + catch + { + return path; + } + } + + /// + /// Converts an Office file to PDF using GhostPDL. + /// Input and output paths are resolved to absolute paths (required by SmartOffice). + /// + public static void ConvertToPdf(string inputPath, string outputPath) + { + ConvertToPdf(inputPath, outputPath, null); + } + + /// + /// Converts an Office file to PDF using the given GhostPDL library. + /// + public static void ConvertToPdf(string inputPath, string outputPath, GhostscriptVersionInfo pdlVersion) + { + if (string.IsNullOrWhiteSpace(inputPath)) + { + throw new ArgumentNullException("inputPath"); + } + + if (string.IsNullOrWhiteSpace(outputPath)) + { + throw new ArgumentNullException("outputPath"); + } + + if (!File.Exists(inputPath)) + { + throw new FileNotFoundException("Could not find input file.", inputPath); + } + + if (pdlVersion == null) + { + pdlVersion = GhostscriptVersionInfo.GetGhostPdlVersion(); + } + else if (!pdlVersion.IsGhostPdl) + { + throw new GhostscriptPdlLibraryNotFoundException(); + } + + string inputFull = Path.GetFullPath(inputPath); + string outputFull = Path.GetFullPath(outputPath); + + string outputDirectory = Path.GetDirectoryName(outputFull); + if (!string.IsNullOrEmpty(outputDirectory) && !Directory.Exists(outputDirectory)) + { + Directory.CreateDirectory(outputDirectory); + } + + using (GhostscriptProcessor processor = new GhostscriptProcessor(pdlVersion, false)) + { + processor.Process(new[] + { + "-ghostscript.net", + "-dNOPAUSE", + "-dBATCH", + "-dNOPROMPT", + "-sDEVICE=pdfwrite", + "-sOutputFile=" + outputFull, + "-f", + inputFull + }); + } + + if (!File.Exists(outputFull) || new FileInfo(outputFull).Length == 0) + { + throw new GhostscriptPdlLibraryNotFoundException( + GhostscriptOffice.CommercialLicenseRequiredMessage + + " The library at '" + pdlVersion.DllPath + "' did not convert '" + inputFull + "' to PDF. " + + "Use the licensed GhostPDL/SmartOffice native library, not standard Ghostscript."); + } + } + + /// + /// Converts an Office file to a temporary PDF and returns that path. + /// The caller owns the file and should delete it when finished. + /// + public static string ConvertToTemporaryPdf(string inputPath) + { + return ConvertToTemporaryPdf(inputPath, null); + } + + /// + /// Converts an Office file to a temporary PDF using the given GhostPDL library. + /// + public static string ConvertToTemporaryPdf(string inputPath, GhostscriptVersionInfo pdlVersion) + { + string outputPath = Path.Combine(Path.GetTempPath(), "gsnet-office-" + Guid.NewGuid().ToString("N") + ".pdf"); + ConvertToPdf(inputPath, outputPath, pdlVersion); + return outputPath; + } + + /// + /// Tries to infer an Office file extension from a stream's magic bytes. + /// + internal static bool TryDetectOfficeExtension(Stream stream, out string extension) + { + extension = null; + + if (stream == null || !stream.CanSeek || stream.Length < 8) + { + return false; + } + + long original = stream.Position; + try + { + stream.Position = 0; + byte[] header = new byte[Math.Min(4096, (int)stream.Length)]; + int read = stream.Read(header, 0, header.Length); + if (read < 8) + { + return false; + } + + // OLE compound document (.doc / .xls / .ppt) + if (header[0] == 0xD0 && header[1] == 0xCF && header[2] == 0x11 && header[3] == 0xE0 && + header[4] == 0xA1 && header[5] == 0xB1 && header[6] == 0x1A && header[7] == 0xE1) + { + extension = ".doc"; + return true; + } + + // ZIP-based OOXML / ODF + if (header[0] == (byte)'P' && header[1] == (byte)'K') + { + string ascii = Encoding.ASCII.GetString(header, 0, read); + if (ascii.IndexOf("word/", StringComparison.OrdinalIgnoreCase) >= 0) + { + extension = ".docx"; + return true; + } + if (ascii.IndexOf("xl/", StringComparison.OrdinalIgnoreCase) >= 0) + { + extension = ".xlsx"; + return true; + } + if (ascii.IndexOf("ppt/", StringComparison.OrdinalIgnoreCase) >= 0) + { + extension = ".pptx"; + return true; + } + if (ascii.IndexOf("opendocument.text", StringComparison.OrdinalIgnoreCase) >= 0) + { + extension = ".odt"; + return true; + } + if (ascii.IndexOf("opendocument.spreadsheet", StringComparison.OrdinalIgnoreCase) >= 0) + { + extension = ".ods"; + return true; + } + if (ascii.IndexOf("opendocument.presentation", StringComparison.OrdinalIgnoreCase) >= 0) + { + extension = ".odp"; + return true; + } + } + + return false; + } + finally + { + stream.Position = original; + } + } + } +} diff --git a/Ghostscript.NET/GhostscriptPipedOutput.cs b/Ghostscript.NET/GhostscriptPipedOutput.cs index cd92562..f7edf08 100644 --- a/Ghostscript.NET/GhostscriptPipedOutput.cs +++ b/Ghostscript.NET/GhostscriptPipedOutput.cs @@ -112,11 +112,10 @@ protected virtual void Dispose(bool disposing) if (_thread != null) { - // check if the thread is still running - if (_thread.ThreadState == ThreadState.Running) + // Thread.Abort is not supported on .NET Core; closing the pipe unblocks Read. + if (_thread.IsAlive) { - // abort the thread - _thread.Abort(); + _thread.Join(TimeSpan.FromSeconds(2)); } _thread = null; @@ -181,7 +180,11 @@ public byte[] Data { get { - _thread.Join(); + if (!_thread.Join(TimeSpan.FromSeconds(30))) + { + throw new TimeoutException("Timed out reading Ghostscript piped output."); + } + return _data.ToArray(); } } diff --git a/Ghostscript.NET/GhostscriptVersionInfo.cs b/Ghostscript.NET/GhostscriptVersionInfo.cs index 9683795..5990b3d 100644 --- a/Ghostscript.NET/GhostscriptVersionInfo.cs +++ b/Ghostscript.NET/GhostscriptVersionInfo.cs @@ -46,6 +46,7 @@ public class GhostscriptVersionInfo private string _libPath; private GhostscriptLicense _licenseType; private GhostscriptDiscoverySource _source; + private GhostscriptNativeKind _nativeKind; #endregion @@ -78,6 +79,7 @@ public GhostscriptVersionInfo(Version version, string dllPath, string libPath, G _libPath = libPath; _licenseType = licenseType; _source = source; + _nativeKind = DetectNativeKind(dllPath); } #endregion @@ -89,6 +91,7 @@ public GhostscriptVersionInfo(string customDllPath) _libPath = string.Empty; _licenseType = GhostscriptLicense.GPL; _source = GhostscriptDiscoverySource.Custom; + _nativeKind = DetectNativeKind(customDllPath); } #region Version @@ -151,6 +154,27 @@ public GhostscriptDiscoverySource Source #endregion + #region NativeKind + + /// + /// Gets whether this library is Ghostscript or GhostPDL. + /// GhostPDL is required for Microsoft Office files. + /// + public GhostscriptNativeKind NativeKind + { + get { return _nativeKind; } + } + + /// + /// True when this native library is GhostPDL (gpdldll64.dll / libgpdl.so). + /// + public bool IsGhostPdl + { + get { return _nativeKind == GhostscriptNativeKind.GhostPdl; } + } + + #endregion + #region ToString /// @@ -158,7 +182,7 @@ public GhostscriptDiscoverySource Source /// public override string ToString() { - return string.Format("Licence: {0}, Version: {1}, Source: {2}, Dll: {3}, Lib: {4}", _licenseType, _version, _source, _dllPath, _libPath); + return string.Format("Licence: {0}, Version: {1}, Kind: {2}, Source: {3}, Dll: {4}, Lib: {5}", _licenseType, _version, _nativeKind, _source, _dllPath, _libPath); } #endregion @@ -567,6 +591,72 @@ public static GhostscriptVersionInfo GetPreferredVersion(GhostscriptLicense lice throw new GhostscriptLibraryNotInstalledException(); } + /// + /// Preferred Ghostscript library for viewing. Falls back to Ghostscript next to GhostPDL, + /// then GhostPDL itself, so Office files work when only a GhostPDL install is present. + /// + public static GhostscriptVersionInfo GetPreferredVersionOrPdl() + { + GhostscriptVersionInfo bundled; + if (TryGetBundledVersion(out bundled)) + { + return bundled; + } + + GhostscriptVersionInfo system = TryGetLastInstalledSystemVersion( + GhostscriptLicense.GPL | GhostscriptLicense.AFPL | GhostscriptLicense.Artifex, + GhostscriptLicense.GPL); + if (system != null) + { + return system; + } + + GhostscriptVersionInfo pdl; + if (TryGetGhostPdlVersion(out pdl)) + { + GhostscriptVersionInfo gsBesidePdl; + if (TryGetGhostscriptBeside(pdl.DllPath, out gsBesidePdl)) + { + return gsBesidePdl; + } + + return pdl; + } + + throw new GhostscriptLibraryNotInstalledException(); + } + + private static bool TryGetGhostscriptBeside(string nativeLibraryPath, out GhostscriptVersionInfo version) + { + version = null; + + if (string.IsNullOrWhiteSpace(nativeLibraryPath)) + { + return false; + } + + string directory = Path.GetDirectoryName(nativeLibraryPath); + string found = FindLibraryInDirectory(directory, GetBundledLibraryNames()); + if (string.IsNullOrEmpty(found) || CrossPlatformNativeLibraryHelper.IsGhostPdlLibrary(found)) + { + return false; + } + + if (!CrossPlatformNativeLibraryHelper.IsLibraryCompatible(found)) + { + return false; + } + + Version gsVersion = ReadBundledVersionMetadata(directory) ?? ParseVersionFromString(Path.GetFileName(found)) ?? new Version(0, 0); + version = new GhostscriptVersionInfo( + gsVersion, + found, + directory, + GhostscriptLicense.Artifex, + GhostscriptDiscoverySource.Custom); + return true; + } + #endregion #region TryGetBundledVersion / GetBundledVersion @@ -797,6 +887,212 @@ private static Version ReadBundledVersionMetadata(string directory) #endregion + #region GetPreferredVersionForInput + + /// + /// Returns GhostPDL when is an Office file, otherwise the preferred Ghostscript library. + /// + public static GhostscriptVersionInfo GetPreferredVersionForInput(string inputPath) + { + if (GhostscriptOffice.IsOfficeFile(inputPath)) + { + return GetGhostPdlVersion(); + } + + return GetPreferredVersion(); + } + + #endregion + + #region GhostPDL discovery + + /// + /// True when a GhostPDL native library can be located. + /// + public static bool IsGhostPdlInstalled + { + get + { + GhostscriptVersionInfo version; + return TryGetGhostPdlVersion(out version); + } + } + + /// + /// Gets a GhostPDL native library. Throws if none is found. + /// Office files require GhostPDL, not standard Ghostscript. + /// + public static GhostscriptVersionInfo GetGhostPdlVersion() + { + GhostscriptVersionInfo version; + if (TryGetGhostPdlVersion(out version)) + { + return version; + } + + throw new GhostscriptPdlLibraryNotFoundException(); + } + + /// + /// Tries to locate a GhostPDL native library. + /// Search order: GHOSTPDL_DLL / GPDL_DLL, the application folder + /// (drop-in gpdldll / libgpdl from Ghostscript.NET.Office), + /// then the same directory as a discovered Ghostscript DLL. + /// + public static bool TryGetGhostPdlVersion(out GhostscriptVersionInfo version) + { + version = null; + + string libraryPath = FindGhostPdlLibraryPath(); + if (string.IsNullOrEmpty(libraryPath) || !File.Exists(libraryPath)) + { + return false; + } + + if (!CrossPlatformNativeLibraryHelper.IsLibraryCompatible(libraryPath)) + { + return false; + } + + string directory = Path.GetDirectoryName(libraryPath) ?? string.Empty; + Version gsVersion = ReadBundledVersionMetadata(directory) ?? ParseVersionFromString(Path.GetFileName(libraryPath)) ?? new Version(0, 0); + + version = new GhostscriptVersionInfo( + gsVersion, + libraryPath, + directory, + GhostscriptLicense.Artifex, + FileIsBundled(libraryPath) ? GhostscriptDiscoverySource.Bundled : GhostscriptDiscoverySource.Custom); + + return true; + } + + private static string FindGhostPdlLibraryPath() + { + string envPath = Environment.GetEnvironmentVariable("GHOSTPDL_DLL"); + if (string.IsNullOrWhiteSpace(envPath)) + { + envPath = Environment.GetEnvironmentVariable("GPDL_DLL"); + } + + if (!string.IsNullOrWhiteSpace(envPath) && File.Exists(envPath)) + { + return envPath; + } + + string[] libraryNames = CrossPlatformNativeLibraryHelper.GetGhostPdlLibraryNames(Environment.Is64BitProcess); + + string bundled = FindLibraryInProbeDirectories(libraryNames); + if (!string.IsNullOrEmpty(bundled)) + { + return bundled; + } + + GhostscriptVersionInfo gs; + if (TryGetBundledVersion(out gs)) + { + string besideGs = FindLibraryInDirectory(Path.GetDirectoryName(gs.DllPath), libraryNames); + if (!string.IsNullOrEmpty(besideGs)) + { + return besideGs; + } + } + + GhostscriptVersionInfo systemGs = TryGetLastInstalledSystemVersion( + GhostscriptLicense.GPL | GhostscriptLicense.AFPL | GhostscriptLicense.Artifex, + GhostscriptLicense.GPL); + if (systemGs != null) + { + string besideGs = FindLibraryInDirectory(Path.GetDirectoryName(systemGs.DllPath), libraryNames); + if (!string.IsNullOrEmpty(besideGs)) + { + return besideGs; + } + } + + return null; + } + + private static string FindLibraryInProbeDirectories(string[] libraryNames) + { + string baseDirectory = AppContext.BaseDirectory; + if (string.IsNullOrEmpty(baseDirectory)) + { + baseDirectory = AppDomain.CurrentDomain.BaseDirectory; + } + + string rid = GetCurrentRuntimeIdentifier(); + + List probeDirectories = new List(); + AddProbeDirectory(probeDirectories, baseDirectory); + AddProbeDirectory(probeDirectories, Path.Combine(baseDirectory, "native")); + + if (!string.IsNullOrEmpty(rid)) + { + AddProbeDirectory(probeDirectories, Path.Combine(baseDirectory, "runtimes", rid, "native")); + AddProbeDirectory(probeDirectories, Path.Combine(baseDirectory, rid, "native")); + } + + foreach (string directory in probeDirectories) + { + string found = FindLibraryInDirectory(directory, libraryNames); + if (!string.IsNullOrEmpty(found)) + { + return found; + } + } + + return null; + } + + private static string FindLibraryInDirectory(string directory, string[] libraryNames) + { + if (string.IsNullOrEmpty(directory) || !Directory.Exists(directory) || libraryNames == null) + { + return null; + } + + foreach (string libraryName in libraryNames) + { + string candidate = Path.Combine(directory, libraryName); + if (File.Exists(candidate)) + { + return candidate; + } + } + + return null; + } + + private static bool FileIsBundled(string libraryPath) + { + string baseDirectory = AppContext.BaseDirectory ?? AppDomain.CurrentDomain.BaseDirectory; + if (string.IsNullOrEmpty(baseDirectory) || string.IsNullOrEmpty(libraryPath)) + { + return false; + } + + try + { + string fullLibrary = Path.GetFullPath(libraryPath); + string fullBase = Path.GetFullPath(baseDirectory); + return fullLibrary.StartsWith(fullBase, StringComparison.OrdinalIgnoreCase); + } + catch + { + return false; + } + } + + private static GhostscriptNativeKind DetectNativeKind(string dllPath) + { + return CrossPlatformNativeLibraryHelper.IsGhostPdlLibrary(dllPath) + ? GhostscriptNativeKind.GhostPdl + : GhostscriptNativeKind.Ghostscript; + } + + #endregion + #region IsGhostscriptInstalled /// diff --git a/Ghostscript.NET/Helpers/CrossPlatformNativeLibraryHelper.cs b/Ghostscript.NET/Helpers/CrossPlatformNativeLibraryHelper.cs index 8df57e2..132bf85 100644 --- a/Ghostscript.NET/Helpers/CrossPlatformNativeLibraryHelper.cs +++ b/Ghostscript.NET/Helpers/CrossPlatformNativeLibraryHelper.cs @@ -84,6 +84,63 @@ public static string GetGhostscriptLibraryName(bool is64Bit) return is64Bit ? "gsdll64.dll" : "gsdll32.dll"; } + /// + /// Gets the expected GhostPDL library name for the current platform. + /// + public static string GetGhostPdlLibraryName(bool is64Bit) + { + if (CurrentPlatform == OSPlatform.Windows) + return is64Bit ? "gpdldll64.dll" : "gpdldll32.dll"; + else if (CurrentPlatform == OSPlatform.Linux) + return "libgpdl.so"; + else if (CurrentPlatform == OSPlatform.OSX) + return "libgpdl.dylib"; + else + return is64Bit ? "gpdldll64.dll" : "gpdldll32.dll"; + } + + /// + /// Filenames to probe when locating a GhostPDL native library. + /// + public static string[] GetGhostPdlLibraryNames(bool is64Bit) + { + if (CurrentPlatform == OSPlatform.Windows) + { + return new[] { GetGhostPdlLibraryName(is64Bit) }; + } + + if (CurrentPlatform == OSPlatform.Linux) + { + return new[] { "libgpdl.so.10", "libgpdl.so.9", "libgpdl.so" }; + } + + if (CurrentPlatform == OSPlatform.OSX) + { + return new[] { "libgpdl.dylib", "libgpdl.so" }; + } + + return new[] { GetGhostPdlLibraryName(is64Bit) }; + } + + /// + /// Returns true when the path looks like a GhostPDL native library. + /// + public static bool IsGhostPdlLibrary(string libraryPath) + { + if (string.IsNullOrWhiteSpace(libraryPath)) + { + return false; + } + + string name = Path.GetFileName(libraryPath); + if (string.IsNullOrEmpty(name)) + { + return false; + } + + return name.IndexOf("gpdl", StringComparison.OrdinalIgnoreCase) >= 0; + } + /// /// Checks if a native library is compatible with the current process architecture. /// diff --git a/Ghostscript.NET/Helpers/StreamHelper.cs b/Ghostscript.NET/Helpers/StreamHelper.cs index 797cdca..34dd300 100644 --- a/Ghostscript.NET/Helpers/StreamHelper.cs +++ b/Ghostscript.NET/Helpers/StreamHelper.cs @@ -56,6 +56,12 @@ public static string GetStreamExtension(Stream stream) stream.Position = 0; + string officeExtension; + if (GhostscriptOffice.TryDetectOfficeExtension(stream, out officeExtension)) + { + return officeExtension; + } + string extension = string.Empty; if (test[0] == 0x25 && test[1] == 0x21) // standard ps or eps signature @@ -123,7 +129,7 @@ public static string GetStreamExtension(Stream stream) if (string.IsNullOrWhiteSpace(extension)) { - throw new FormatException("Stream format is not valid! Please make sure it's PDF, PS or EPS."); + throw new FormatException("Stream format is not valid! Please make sure it's PDF, PS, EPS, or a supported Office file."); } return extension; diff --git a/Ghostscript.NET/Microsoft.WinAny.Helper/Interop/DynamicNativeLibrary.cs b/Ghostscript.NET/Microsoft.WinAny.Helper/Interop/DynamicNativeLibrary.cs index 05c9472..ed2230a 100644 --- a/Ghostscript.NET/Microsoft.WinAny.Helper/Interop/DynamicNativeLibrary.cs +++ b/Ghostscript.NET/Microsoft.WinAny.Helper/Interop/DynamicNativeLibrary.cs @@ -34,6 +34,7 @@ // Copyright (C) 2004-2012 Joachim Bauch (mail@joachim-bauch.de). using System; +using System.Reflection; using System.Runtime.InteropServices; namespace Microsoft.WinAny.Interop @@ -680,6 +681,17 @@ public Delegate GetDelegateForFunction(string procName, Type delegateType) { IntPtr procAddress = this.GetProcAddress(procName); + // 32-bit GhostPDL (MSVC) exports stdcall names such as _gsapi_revision@8. + // NativeAssets gsdll32.dll uses undecorated names; try both. + if (procAddress == IntPtr.Zero && !Environment.Is64BitProcess) + { + string decorated = GetStdcallExportName(procName, delegateType); + if (decorated != procName) + { + procAddress = this.GetProcAddress(decorated); + } + } + if (procAddress != IntPtr.Zero) { return Marshal.GetDelegateForFunctionPointer(procAddress, delegateType); @@ -688,6 +700,44 @@ public Delegate GetDelegateForFunction(string procName, Type delegateType) return null; } + private static string GetStdcallExportName(string procName, Type delegateType) + { + if (string.IsNullOrEmpty(procName) || delegateType == null || procName[0] == '_') + { + return procName; + } + + MethodInfo invoke = delegateType.GetMethod("Invoke"); + if (invoke == null) + { + return procName; + } + + int stackBytes = 0; + ParameterInfo[] parameters = invoke.GetParameters(); + for (int i = 0; i < parameters.Length; i++) + { + Type type = parameters[i].ParameterType; + int size; + if (type.IsByRef || !type.IsValueType) + { + size = IntPtr.Size; + } + else if (type.IsEnum) + { + size = Marshal.SizeOf(Enum.GetUnderlyingType(type)); + } + else + { + size = Marshal.SizeOf(type); + } + + stackBytes += (size + 3) & ~3; + } + + return "_" + procName + "@" + stackBytes.ToString(); + } + #endregion #region GetDelegateForFunction diff --git a/Ghostscript.NET/OutputDevices/GhostscriptDevice.cs b/Ghostscript.NET/OutputDevices/GhostscriptDevice.cs index b7ca224..1378e09 100644 --- a/Ghostscript.NET/OutputDevices/GhostscriptDevice.cs +++ b/Ghostscript.NET/OutputDevices/GhostscriptDevice.cs @@ -249,6 +249,12 @@ public void Process() public void Process(GhostscriptStdIO stdIO_callback) { + if (GhostscriptOffice.ContainsOfficeFile(this.InputFiles)) + { + this.Process(GhostscriptVersionInfo.GetGhostPdlVersion(), false, stdIO_callback); + return; + } + this.Process(GhostscriptVersionInfo.GetLastInstalledVersion(GhostscriptLicense.GPL | GhostscriptLicense.AFPL, GhostscriptLicense.GPL), true, stdIO_callback); diff --git a/Ghostscript.NET/PDFA3Converter/PDFA3Converter.cs b/Ghostscript.NET/PDFA3Converter/PDFA3Converter.cs index 7c7306d..7e62a7e 100644 --- a/Ghostscript.NET/PDFA3Converter/PDFA3Converter.cs +++ b/Ghostscript.NET/PDFA3Converter/PDFA3Converter.cs @@ -53,9 +53,18 @@ public class PDFA3Converter /// - /// The constructor of the class accepts both input and output path for PDF conversion. + /// Creates a converter that uses the preferred Ghostscript library + /// (NativeAssets, then a system install). /// - /// PDF input path + public PDFA3Converter() + : this(GhostscriptVersionInfo.GetPreferredVersion().DllPath) + { + } + + /// + /// Creates a converter that loads Ghostscript from . + /// + /// Full path to the Ghostscript native library. public PDFA3Converter(String gsdll) { @@ -265,36 +274,28 @@ public bool ConvertToPDFA3(string sourcePDFPath, string targetPDFPath) } GhostscriptVersionInfo gsVersion = new GhostscriptVersionInfo(GSDLLPath); - GhostscriptLibrary ghostscriptLibrary = new GhostscriptLibrary(gsVersion); - GhostscriptPipedOutput gsPipedOutput = new GhostscriptPipedOutput(); List switches = new List(); - switches.Add(""); // first parameter might be ignored + switches.Add("-ghostscript.net"); + switches.Add("-dNOPAUSE"); + switches.Add("-dBATCH"); switches.Add("-P"); // allow access to resources within the current directory - switches.Add("-dPDFA=3"); // convert to A/3 pat 1/3 - // switches.Add("-dCompressStreams=false") hat problems as apparently XMP Metadata was compressed by ZUGFeRD. Obsolete in the meantime + switches.Add("-dPDFA=3"); // convert to A/3 part 1/3 switches.Add("-sColorConversionStrategy=RGB"); // necessary for PDF/A conversion switches.Add("-sDEVICE=pdfwrite"); // Device for rasterization. Mandatory - switches.Add($"-o{targetPDFPath}"); // Output path + switches.Add("-sOutputFile=" + targetPDFPath); // Output path switches.Add("-dNOSAFER"); // Disable safe mode switches.Add("-dPDFACompatibilityPolicy=1"); // convert to A/3 part 2/3 switches.Add("-dRenderIntent=3"); // convert to A/3 part 3/3 - switches.Add(PostScriptBigScriptPath); // PDFMark program file that shall be interpreted. - // see https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdfmark_reference.pdf - // and https://gitlab.com/crossref/pdfmark - switches.Add(sourcePDFPath); // PDF input file + switches.Add(PostScriptBigScriptPath); + switches.Add(sourcePDFPath); - bool success = false; - using (GhostscriptProcessor processor = new GhostscriptProcessor(ghostscriptLibrary)) + using (GhostscriptProcessor processor = new GhostscriptProcessor(gsVersion, false)) { - VerboseMsgBoxOutput stdio = new VerboseMsgBoxOutput(); - processor.StartProcessing(switches.ToArray(), stdio); - - // (erfolglose) Versuche, das Hngen zu vermeiden... - processor.Dispose(); + processor.Process(switches.ToArray(), new VerboseMsgBoxOutput()); } - success = true; - return success; + + return File.Exists(targetPDFPath); } // !ConvertToPDFA3() diff --git a/Ghostscript.NET/Processor/GhostscriptProcessor.cs b/Ghostscript.NET/Processor/GhostscriptProcessor.cs index e408a48..a101b55 100644 --- a/Ghostscript.NET/Processor/GhostscriptProcessor.cs +++ b/Ghostscript.NET/Processor/GhostscriptProcessor.cs @@ -118,6 +118,15 @@ public GhostscriptProcessor() : this(GhostscriptVersionInfo.GetLastInstalledVersion(GhostscriptLicense.GPL | GhostscriptLicense.AFPL, GhostscriptLicense.GPL), false) { } + /// + /// Creates a processor that loads GhostPDL when is an Office file, + /// otherwise the preferred Ghostscript library. + /// + public static GhostscriptProcessor CreateForInput(string inputPath) + { + return new GhostscriptProcessor(GhostscriptVersionInfo.GetPreferredVersionForInput(inputPath), false); + } + #endregion #region Constructor - library @@ -208,6 +217,24 @@ protected virtual void Dispose(bool disposing) #endregion + private void EnsureGhostPdlLibrary() + { + if (_gs != null && _gs.VersionInfo != null && _gs.VersionInfo.IsGhostPdl) + { + return; + } + + GhostscriptLibrary replacement = new GhostscriptLibrary(GhostscriptVersionInfo.GetGhostPdlVersion(), false); + + if (_processorOwnsLibrary && _gs != null) + { + _gs.Dispose(); + } + + _gs = replacement; + _processorOwnsLibrary = true; + } + #region Process - device public void Process(GhostscriptDevice device) @@ -277,6 +304,12 @@ public void StartProcessing(string[] args, GhostscriptStdIO stdIO_callback) throw new ArgumentOutOfRangeException("args"); } + if (GhostscriptOffice.ContainsOfficeFile(args)) + { + EnsureGhostPdlLibrary(); + args = GhostscriptOffice.PrepareProcessorArgs(args); + } + // Prepare arguments: if the native gsapi_set_arg_encoding API is supported // we will set the requested encoding and pass native-encoded argv pointers // (UTF-16LE on Windows, UTF-8 on non-Windows). Otherwise fall back to diff --git a/Ghostscript.NET/Rasterizer/GhostscriptRasterizer.cs b/Ghostscript.NET/Rasterizer/GhostscriptRasterizer.cs index 4bc23c2..372d671 100644 --- a/Ghostscript.NET/Rasterizer/GhostscriptRasterizer.cs +++ b/Ghostscript.NET/Rasterizer/GhostscriptRasterizer.cs @@ -143,7 +143,7 @@ public void Open(Stream stream) throw new ArgumentNullException("stream"); } - this.Open(stream, GhostscriptVersionInfo.GetLastInstalledVersion(GhostscriptLicense.GPL | GhostscriptLicense.AFPL, GhostscriptLicense.GPL), false); + this.Open(stream, GhostscriptVersionInfo.GetPreferredVersionOrPdl(), false); } #endregion @@ -157,7 +157,7 @@ public void Open(string path) throw new FileNotFoundException("Could not find input file.", path); } - this.Open(path, GhostscriptVersionInfo.GetLastInstalledVersion(GhostscriptLicense.GPL | GhostscriptLicense.AFPL, GhostscriptLicense.GPL), false); + this.Open(path, GhostscriptVersionInfo.GetPreferredVersionOrPdl(), false); } #endregion diff --git a/Ghostscript.NET/Viewer/GhostscriptViewer.cs b/Ghostscript.NET/Viewer/GhostscriptViewer.cs index 1fdb681..5677211 100644 --- a/Ghostscript.NET/Viewer/GhostscriptViewer.cs +++ b/Ghostscript.NET/Viewer/GhostscriptViewer.cs @@ -186,7 +186,7 @@ public void Open(string path) throw new FileNotFoundException("Could not find input file.", path); } - this.Open(path, GhostscriptVersionInfo.GetLastInstalledVersion(GhostscriptLicense.GPL | GhostscriptLicense.AFPL, GhostscriptLicense.GPL), false); + this.Open(path, GhostscriptVersionInfo.GetPreferredVersionOrPdl(), false); } #endregion @@ -230,7 +230,7 @@ public void Open(string path, GhostscriptVersionInfo versionInfo, bool dllFromMe this.Close(); - _filePath = path; + _filePath = ResolveInputPath(path); _interpreter = new GhostscriptInterpreter(versionInfo, dllFromMemory); @@ -273,7 +273,7 @@ public void Open(string path, byte[] library) this.Close(); - _filePath = path; + _filePath = ResolveInputPath(path); _interpreter = new GhostscriptInterpreter(library); @@ -309,6 +309,21 @@ public void RegisterTempFile(string path) _fileCleanupHelper.Add(path); } + /// + /// Converts Office files to a temporary PDF via GhostPDL so the existing PDF viewer path can be used. + /// + private string ResolveInputPath(string path) + { + if (!GhostscriptOffice.IsOfficeFile(path)) + { + return path; + } + + string pdfPath = GhostscriptOffice.ConvertToTemporaryPdf(path); + _fileCleanupHelper.Add(pdfPath); + return pdfPath; + } + #endregion #region Open - library @@ -373,6 +388,8 @@ private void Open() List args = new List(); args.Add("-gsnet"); + args.Add("-dNOPAUSE"); + args.Add("-dNOPROMPT"); args.Add("-sDEVICE=display"); if (Environment.Is64BitProcess) diff --git a/README.md b/README.md index 6e9ee1f..464cad1 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Target: .NET Standard 2.0](https://img.shields.io/badge/.NET-Standard%202.0-blue)](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) [![Discord](https://img.shields.io/discord/770681584617652264?color=6A7EC2&logo=discord&logoColor=ffffff)](https://artifex.com/discord/artifex/) -**Ghostscript.NET** is a managed C# wrapper for the [Ghostscript](https://ghostscript.com) native library (`gsdll64.dll` / `libgs.so`). It lets you rasterize, convert, and process PDF, PostScript, and EPS files from any .NET application without shelling out to a command-line process. +**Ghostscript.NET** is a managed C# wrapper for the [Ghostscript](https://ghostscript.com) native library (`gsdll64.dll` / `libgs.so`). It lets you rasterize, convert, and process PDF, PostScript, EPS, and (with a licensed GhostPDL library) Microsoft Office files from any .NET application without shelling out to a command-line process. ```powershell Install-Package Ghostscript.NET @@ -29,6 +29,7 @@ Install-Package Ghostscript.NativeAssets - [Code examples](#code-examples) - [API overview](#api-overview) - [Finding the Ghostscript native library](#finding-the-ghostscript-native-library) +- [Office files (GhostPDL)](#office-files-ghostpdl) - [PDF/A-3 conversion](#pdfa-3-conversion) - [Documentation](#documentation) - [License](#license) @@ -160,6 +161,7 @@ processor.Process(new[] | **Image export** | Save pages as PNG, JPEG, TIFF, BMP, or any SkiaSharp-supported format | | **In-memory rendering** | Rasterize without writing intermediate files to disk | | **PDF conversion** | Convert PS/EPS to PDF, compress PDFs, apply `pdfwrite` device settings | +| **Office files** | Convert and rasterize Word, Excel, PowerPoint (and related) files when a licensed GhostPDL library is present | | **Custom switches** | Pass any Ghostscript command-line switch directly via `CustomSwitches` or `Process(args[])` | | **Progress events** | `GhostscriptProcessor` raises `Started`, `Processing` (per-page), `Error`, and `Completed` events | | **Multi-instance** | Multiple `GhostscriptProcessor` or `GhostscriptRasterizer` instances can run in parallel | @@ -325,6 +327,7 @@ rasterizer.Open("input.pdf", dllBytes); | `GhostscriptProcessor` | `Ghostscript.NET.Processor` | Run Ghostscript with any argument array; exposes progress events | | `GhostscriptViewer` | `Ghostscript.NET.Viewer` | Interactive viewer with zoom and progressive rendering | | `GhostscriptVersionInfo` | `Ghostscript.NET` | Discover installed Ghostscript versions; specify DLL path | +| `GhostscriptOffice` | `Ghostscript.NET` | Convert Office files to PDF via GhostPDL; detect supported extensions | | `GhostscriptLibrary` | `Ghostscript.NET` | Low-level native library loader and P/Invoke surface | | `GhostscriptStdIO` | `Ghostscript.NET` | Abstract base class for stdin/stdout/stderr callbacks | | `GhostscriptPngDevice` | `Ghostscript.NET.OutputDevices` | Typed device for PNG output with all PNG switches | @@ -352,7 +355,8 @@ rasterizer.Open("input.pdf", dllBytes); | Member | Type | Description | |---|---|---| -| `Process(string[] args)` | Method | Run Ghostscript with a raw argument array | +| `CreateForInput(string path)` | Static method | Optional: load GhostPDL up front for an Office path | +| `Process(string[] args)` | Method | Run Ghostscript; loads GhostPDL automatically if args include an Office file | | `Process(GhostscriptDevice device)` | Method | Run using a typed device object | | `Process(string[] args, GhostscriptStdIO callback)` | Method | Run with stdout/stderr capture | | `StartProcessing(...)` | Method | Alias for `Process`; included for API compatibility | @@ -379,6 +383,10 @@ rasterizer.Open("input.pdf", dllBytes); | `.DllPath` | Property | Path to the native library file | | `.Version` | Property | `System.Version` of the detected installation | | `.Source` | Property | `Bundled`, `System`, or `Custom` | +| `.NativeKind` / `.IsGhostPdl` | Property | Ghostscript vs GhostPDL native library | +| `GetGhostPdlVersion()` | Static method | Locates `gpdldll64.dll` / `libgpdl.so` (required for Office files) | +| `TryGetGhostPdlVersion(out version)` | Static method | Same lookup without throwing | +| `GetPreferredVersionForInput(path)` | Static method | GhostPDL for Office paths, otherwise preferred Ghostscript | --- @@ -403,6 +411,65 @@ rasterizer.Open("input.pdf", dll); --- +## Office files (GhostPDL) + +Standard Ghostscript (`gsdll64.dll` / `Ghostscript.NativeAssets`) cannot open Word, Excel, or PowerPoint files. Office support uses **GhostPDL** (`gpdldll64.dll` / `gpdldll32.dll` / `libgpdl.so`), which includes **SmartOffice** and exposes the same `gsapi_*` API. + +SmartOffice is commercial, in-house technology. The GhostPDL native library is **not** published on nuget.org and is **not** included in `Ghostscript.NativeAssets`. Without a commercial Ghostscript.NET license, opening an Office file throws `GhostscriptPdlLibraryNotFoundException` and directs you to [Artifex](https://artifex.com/contact/ghostscript). Licensed users obtain the matching library from the **Ghostscript.NET.Office** repository and copy it into the .NET project. + +Place the file next to your application, under `runtimes//native/`, or set `GHOSTPDL_DLL` (or `GPDL_DLL`) to its full path. After that, **existing Ghostscript.NET processor code does not need to change**: if the argument list includes an Office file, `GhostscriptProcessor` loads GhostPDL automatically (and ignores `-dSAFER` for that job). `CreateForInput` is optional. If `gsdll64.dll` sits beside GhostPDL, the viewer/rasterizer uses it to display the converted PDF. + +**Convert Office to PDF** + +```csharp +using Ghostscript.NET; + +GhostscriptOffice.ConvertToPdf(@"D:\report.docx", @"D:\report.pdf"); +``` + +**Rasterize an Office file** (`GhostscriptRasterizer` / `GhostscriptViewer` convert to a temporary PDF automatically) + +```csharp +using Ghostscript.NET.Rasterizer; + +using var rasterizer = new GhostscriptRasterizer(); +rasterizer.Open(@"D:\report.docx"); + +for (int page = 1; page <= rasterizer.PageCount; page++) +{ + SKBitmap image = rasterizer.GetPage(dpi: 150, pageNumber: page); +} +``` + +**Run GhostPDL with any device** + +Existing `GhostscriptProcessor` samples keep working. Pass an Office path in the argument list and place `gpdldll64.dll` next to the app: + +```csharp +using Ghostscript.NET; +using Ghostscript.NET.Processor; + +GhostscriptVersionInfo gv = GhostscriptVersionInfo.GetLastInstalledVersion(); +using var processor = new GhostscriptProcessor(gv, true); +processor.Process(new[] +{ + "-dBATCH", "-dNOPAUSE", "-dSAFER", + "-sDEVICE=png16m", + "-sOutputFile=page-%03d.png", + @"D:\report.docx" +}); +``` + +`CreateForInput` still loads GhostPDL up front when you already know the input is Office. + +Use **full paths** for Office input and output. GhostPDL allows only one interpreter instance per process. + +Supported extensions include `.doc`, `.docx`, `.xls`, `.xlsx`, `.ppt`, `.pptx`, `.odt`, `.ods`, `.odp`, `.rtf`, and `.csv`. + +Usage with Ghostscript.NET, including sample code, is documented in **Ghostscript.NET.Office**. Maintainers who produce the native libraries see **Ghostscript.NET.Office/BUILD.md**. + +--- + ## PDF/A-3 conversion The `PDFA3Converter` class converts any PDF to PDF/A-3b format and optionally embeds a ZUGFeRD or Factur-X XML invoice. This is the format required by XRechnung (Germany) and Factur-X (France/EU) electronic invoicing standards. diff --git a/Versions.props b/Versions.props index 72bbd06..1fa6312 100644 --- a/Versions.props +++ b/Versions.props @@ -1,7 +1,7 @@ - 1.3.4 + 1.3.5 10.7.1