title: Successfully reading data from printer with ReadPrinter Winspool.drv
body: <p>I'm having some problems when sending raw command to a FGL-enabled Practical Automation ITX3002 ticket printer. I've been searching the whole day and I wasn't able to find a working example of using the ReadPrinter method from the winspool.drv Windows library. </p>
  
  <p>Most code samples I've found, were related to network printers. This is a simple printer connected via usb. I need to retrieve some commands which response structure I already know (composite structure, well documented by the vendor). </p>
  
  <p>I am able to send FGL commands to print normal and diagnostic ticket successfully. My problem, is reading back the data from the printer. I've read the Microsoft documentation found in <a href="http://msdn.microsoft.com/en-us/library/dd162895(v=vs.85).aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/dd162895(v=vs.85).aspx</a> and several other places. The doc doesn't explain how to SEND the data which this method is reading. </p>
  
  <p>So, I really don't know if I have to call WritePrinter with the commands I need, close the handle, then call ReadPrinter to retrieve the data, or if I have to do everything in a single printer handle management (I mean, open, work and close a printer handle).</p>
  
  <p>The vendor has been very patient with me, but the responses don't give me any help on how to get this.</p>
  
  <p>This is my code:</p>
  
  <pre><code>    [DllImport("winspool.Drv", EntryPoint = "ReadPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
      public static extern Boolean ReadPrinter(IntPtr hPrinter, StringBuilder data, Int32 cbBuf, out Int32 pNoBytesRead);
  
  
      public static Boolean ReadBytesFromPrinter(String szPrinterName, out String data)
      {
          Int32 dwError = 0, dwWritten = 0;
          IntPtr hPrinter = new IntPtr(0);
          DOCINFOA di = new DOCINFOA();
          Boolean bSuccess = false; // Assume failure unless you specifically succeed.
          data = null;
  
          di.pDocName = "SendBytesToPrinter";
          di.pDataType = "RAW";
  
  
          // 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))
                  {
                      Int32 maxRead = 256;
                      StringBuilder sbData = new StringBuilder(maxRead);
  
                      //Read Data                
                      bSuccess = ReadPrinter(hPrinter, sbData, maxRead, out dwWritten);
                      data = sbData.ToString();
  
                      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();
              data = null;
          }
  
          return bSuccess;
      }
  </code></pre>
  
  <p>ReadPrinter always return "false", and the call to GetLastWin32Error is always zero. In other words, there is an error, no clues about what, and no data is read back.</p>
  
  <p>I'm sending the commands as explained in <a href="http://support.microsoft.com/kb/322091" rel="nofollow">http://support.microsoft.com/kb/322091</a> and it's successfully working as expected, with print commands and diagnostic ticket printing. </p>
  
  <p>Does anyone knows the right handshaking between the code and the printer? How it's supposed to write the commands, and how to read response back? For me, it's no sense having to create a print job, a print document, and a print page to retrieve the data (I've already tryed that, BTW).  Am I missing something? Am I making something wrong? </p>