title: Simple VB.Net Wrapper for Ghostscript Dll
body: <p>I love Ghostscript.  You can use it to convert pdf's to graphics files, split and/or merge pdf files, make thumbnails, and a whole bunch of other stuff.  And, it's free, open-source software!</p>
  
  <p>There are scads of posts on web sites on how to use Ghostscript from the command line for all sorts of platforms.  But, I could never find a <strong>simple</strong> vb.net dll wrapper that used the Ghostscript dll (gsdll32.dll) instead of starting a process to run the Ghostscript command line app.</p>
  
  <p>So, I came up with this code.  I am posting it here in hopes that others can avoid the frustration I felt looking for something simple and straight forward.  It avoids those goofy arrays of byte array objects you see in some code.  It has minimal error handling, but that can be added to suit your application.</p>
  
  <p>Put this code in a module named "GhostscriptDllLib".</p>
  
  <pre><code>Option Explicit On
  Imports System.Runtime.InteropServices
  
  '--- Simple VB.Net wrapper for Ghostscript gsdll32.dll
  
  '    (Tested using Visual Studio 2010 and Ghostscript 9.06)
  
  Module GhostscriptDllLib
  
    Private Declare Function gsapi_new_instance Lib "gsdll32.dll" _
      (ByRef instance As IntPtr, _
      ByVal caller_handle As IntPtr) As Integer
  
    Private Declare Function gsapi_set_stdio Lib "gsdll32.dll" _
      (ByVal instance As IntPtr, _
      ByVal gsdll_stdin As StdIOCallBack, _
      ByVal gsdll_stdout As StdIOCallBack, _
      ByVal gsdll_stderr As StdIOCallBack) As Integer
  
    Private Declare Function gsapi_init_with_args Lib "gsdll32.dll" _
      (ByVal instance As IntPtr, _
      ByVal argc As Integer, _
      &lt;MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.LPStr)&gt; _
      ByVal argv() As String) As Integer
  
    Private Declare Function gsapi_exit Lib "gsdll32.dll" _
      (ByVal instance As IntPtr) As Integer
  
    Private Declare Sub gsapi_delete_instance Lib "gsdll32.dll" _
      (ByVal instance As IntPtr)
  
    '--- Run Ghostscript with specified arguments
  
    Public Function RunGS(ByVal ParamArray Args() As String) As Boolean
  
      Dim InstanceHndl As IntPtr
      Dim NumArgs As Integer
      Dim StdErrCallback As StdIOCallBack
      Dim StdInCallback As StdIOCallBack
      Dim StdOutCallback As StdIOCallBack
  
      NumArgs = Args.Count
  
      StdInCallback = AddressOf InOutErrCallBack
      StdOutCallback = AddressOf InOutErrCallBack
      StdErrCallback = AddressOf InOutErrCallBack
  
      '--- Shift arguments to begin at index 1 (Ghostscript requirement)
  
      ReDim Preserve Args(NumArgs)
      System.Array.Copy(Args, 0, Args, 1, NumArgs)
  
      '--- Start a new Ghostscript instance
  
      If gsapi_new_instance(InstanceHndl, 0) &lt;&gt; 0 Then
        Return False
        Exit Function
      End If
  
      '--- Set up dummy callbacks
  
      gsapi_set_stdio(InstanceHndl, StdInCallback, StdOutCallback, StdErrCallback)
  
      '--- Run Ghostscript using specified arguments
  
      gsapi_init_with_args(InstanceHndl, NumArgs + 1, Args)
  
      '--- Exit Ghostscript
  
      gsapi_exit(InstanceHndl)
  
      '--- Delete instance
  
      gsapi_delete_instance(InstanceHndl)
  
      Return True
  
    End Function
  
    '--- Delegate function for callbacks
  
    Private Delegate Function StdIOCallBack(ByVal handle As IntPtr, _
      ByVal Strz As IntPtr, ByVal Bytes As Integer) As Integer
  
    '--- Dummy callback for standard input, standard output, and errors
  
    Private Function InOutErrCallBack(ByVal handle As IntPtr, _
      ByVal Strz As IntPtr, ByVal Bytes As Integer) As Integer
  
      Return 0
  
    End Function
  
  End Module
  </code></pre>
  
  <p>The gsdll32.dll file must be where Windows can find it, best in "\Windows\System32" (or "\Windows\SysWOW64" on a 64-bit machine) or in the same folder as your assembly.  It's not the type of dll that has to be registered (in fact, it cannot be registered).</p>
  
  <p>You can then run Ghostscript using a parameter array like this (this sample converts a pdf file to a high quality png file):</p>
  
  <pre><code>Dim PdfFilePath As String = "&lt;Your pdf file path&gt;"
  Dim PngFilePath As String = "&lt;Your png file path&gt;"
  
  RunGS("-q", "-dNOPAUSE", "-dBATCH", "-dSAFER", "-sDEVICE=png16m", _
    "-r600", _"-dDownScaleFactor=6", "-dTextAlphaBits=4", "-dGraphicsAlphaBits=4", _
    "-sPAPERSIZE=letter", "-sOutputFile=" &amp; PngFilePath, PdfFilePath)
  </code></pre>
  
  <p>Or you can run the code using a string array like this (better if arguments are generated dynamically at run time):</p>
  
  <pre><code>Dim PdfFilePath As String = "&lt;Your pdf file path&gt;"
  Dim PngFilePath As String = "&lt;Your png file path&gt;"
  
  Dim Args() As String = {"-q", "-dNOPAUSE", "-dBATCH", "-dSAFER", _
    "-sDEVICE=png16m", "-r600", "-dDownScaleFactor=6", "-dTextAlphaBits=4", _
    "-dGraphicsAlphaBits=4", "-sPAPERSIZE=letter", _
    "-sOutputFile=" &amp; PngFilePath, PdfFilePath}
  
  RunGS(Args)
  </code></pre>
  
  <p>Notes:</p>
  
  <ul>
  <li>Do not enclose input or output file names (paths) in quotes as you
  would for the  command line application</li>
  <li>Do not escape back-slashes (i.e. "c:path\file.pdf" is ok, "c:path\\file.pdf" is not)</li>
  <li>Do not use the Ghostscript "-o" switch; use "sOutputFile="</li>
  </ul>