title: c# RawPrinterHelper sends data to printer, printer spools and states "printed" but doesnt actually print
body: <p>I am using the RawPrinterHelper class as described here:  <a href="https://support.microsoft.com/en-us/help/322091/how-to-send-raw-data-to-a-printer-by-using-visual-c-.net" rel="noreferrer">https://support.microsoft.com/en-us/help/322091/how-to-send-raw-data-to-a-printer-by-using-visual-c-.net</a></p>
  
  <p>I am using the code exactly as per the example and it appeared to work immediately with no errors - except that it didnt actually print.</p>
  
  <p>Inspected the print queue shows the print job appearing, and immediately disappearing. If I change the properties to keep old prints I can see that it classes the job as "Printed". However nothing has actually printed!</p>
  
  <p>I have tried printing directly to the printers using Notepad, Word and excel and all were successful. I have tried 3 different printers, and even re-done the work on a different machine with a different printer but still have the same issue.</p>
  
  <p>I am using Windows 10 professional, and VS2017.</p>
  
  <p>Any advice would be greatly appreciated.</p>
  
  <pre><code> private void button1_Click(object sender, EventArgs e)
      {
           //Allow the user to select a file.
         OpenFileDialog ofd = new OpenFileDialog();
          if (DialogResult.OK == ofd.ShowDialog(this))
          {
              // Allow the user to select a printer.
              PrintDialog pd = new PrintDialog();
              pd.PrinterSettings = new PrinterSettings();
              if (DialogResult.OK == pd.ShowDialog(this))
              {
                  // Print the file to the printer.
                  RawPrinterHelper.SendFileToPrinter(pd.PrinterSettings.PrinterName, ofd.FileName);
              }
          }
      //other tests - these both return True and the job appears in print queue as "printed"
         // label1.Text = RawPrinterHelper.SendFileToPrinter("Citizen CL-S521", @"C:\Development\Code\myText.txt").ToString();
  
          //label2.Text = RawPrinterHelper.SendStringToPrinter("Citizen CL-S521F", "Test string").ToString();
      }
  
      public class RawPrinterHelper
      {
          // Structure and API declarions:
          [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
          public class DOCINFOA
          {
              [MarshalAs(UnmanagedType.LPStr)]
              public string pDocName;
              [MarshalAs(UnmanagedType.LPStr)]
              public string pOutputFile;
              [MarshalAs(UnmanagedType.LPStr)]
              public string pDataType;
          }
          [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
          public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
  
          [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
          public static extern bool ClosePrinter(IntPtr hPrinter);
  
          [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
          public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
  
          [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
          public static extern bool EndDocPrinter(IntPtr hPrinter);
  
          [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
          public static extern bool StartPagePrinter(IntPtr hPrinter);
  
          [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
          public static extern bool EndPagePrinter(IntPtr hPrinter);
  
          [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
          public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
  
          // SendBytesToPrinter()
          // When the function is given a printer name and an unmanaged array
          // of bytes, the function sends those bytes to the print queue.
          // Returns true on success, false on failure.
          public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
          {
              Int32 dwError = 0, dwWritten = 0;
              IntPtr hPrinter = new IntPtr(0);
              DOCINFOA di = new DOCINFOA();
              bool bSuccess = false; // Assume failure unless you specifically succeed.
  
              di.pDocName = "RAW Document";
              // Win7
              di.pDataType = "RAW";
  
              // Win8+
              // di.pDataType = "XPS_PASS";
  
              // Open the printer.
              if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
              {
                  // Start a document.
                  if (StartDocPrinter(hPrinter, 1, di))
                  {
                      // Start a page.
                      if (StartPagePrinter(hPrinter))
                      {
                          // Write your bytes.
                          bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                          EndPagePrinter(hPrinter);
                      }
                      EndDocPrinter(hPrinter);
                  }
                  ClosePrinter(hPrinter);
              }
              // If you did not succeed, GetLastError may give more information
              // about why not.
              if (bSuccess == false)
              {
                  dwError = Marshal.GetLastWin32Error();
              }
              return bSuccess;
          }
  
          public static bool SendFileToPrinter(string szPrinterName, string szFileName)
          {
              // Open the file.
              FileStream fs = new FileStream(szFileName, FileMode.Open);
              // Create a BinaryReader on the file.
              BinaryReader br = new BinaryReader(fs);
              // Dim an array of bytes big enough to hold the file's contents.
              Byte[] bytes = new Byte[fs.Length];
              bool bSuccess = false;
              // Your unmanaged pointer.
              IntPtr pUnmanagedBytes = new IntPtr(0);
              int nLength;
  
              nLength = Convert.ToInt32(fs.Length);
              // Read the contents of the file into the array.
              bytes = br.ReadBytes(nLength);
              // Allocate some unmanaged memory for those bytes.
              pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
              // Copy the managed byte array into the unmanaged array.
              Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
              // Send the unmanaged bytes to the printer.
              bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
              // Free the unmanaged memory that you allocated earlier.
              Marshal.FreeCoTaskMem(pUnmanagedBytes);
              fs.Close();
              fs.Dispose();
              fs = null;
              return bSuccess;
          }
          public static bool SendStringToPrinter(string szPrinterName, string szString)
          {
              IntPtr pBytes;
              Int32 dwCount;
              // How many characters are in the string?
              dwCount = szString.Length;
              // Assume that the printer is expecting ANSI text, and then convert
              // the string to ANSI text.
              pBytes = Marshal.StringToCoTaskMemAnsi(szString);
              // Send the converted ANSI string to the printer.
              SendBytesToPrinter(szPrinterName, pBytes, dwCount);
              Marshal.FreeCoTaskMem(pBytes);
              return true;
          }
      }
  </code></pre>