none
Raw Printing from .NET RRS feed

  • Question

  • Sorry if this isn't the right board, I couldn't find a better choice.

    I'm trying to print raw data to a label printer, and I've converted the code from KB 332091 (http://support.microsoft.com/kb/322091) into VB.NET

    For the printer name, I am selecting from System.Drawing.Printing.PrinterSettings.InstalledPrinters

    All the functions return Success as True, but nothing ever prints. The printer icon doesn't appear in the system tray or anything.

    Does anybody have any ideas on how I can find out what's going wrong, how I can fix it, or any other ways of printing raw data?

    Here's my VB version of the RawPrinterHelper
    Imports System.Runtime  
    Imports System.Runtime.InteropServices  
    Imports System.IO  
     
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _  
    Public Class DOCINFO  
      <MarshalAs(UnmanagedType.LPStr)> Public pDocName As String 
      <MarshalAs(UnmanagedType.LPStr)> Public pOutputFile As String 
      <MarshalAs(UnmanagedType.LPStr)> Public pDataType As String 
    End Class 
     
    ''' <summary>  
    '''   Printing Code  
    ''' </summary>  
    ''' <remarks>  
    '''   Converted from http://support.microsoft.com/kb/322091  
    ''' </remarks>  
    <ProgId("MyProject.RawPrinterHelper"), ClassInterface(ClassInterfaceType.None)> _  
    Public Class RawPrinterHelper  
     
      <DllImport("winspool.drv", CharSet:=CharSet.Unicode, ExactSpelling:=False, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function OpenPrinter(ByVal pPrinterName As StringByRef phPrinter As IntPtr, ByVal pDefault As IntegerAs Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Unicode, ExactSpelling:=False, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function StartDocPrinter(ByVal hPrinter As IntPtr, ByVal Level As IntegerByRef pDocInfo As DOCINFO) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function StartPagePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function WritePrinter(ByVal hPrinter As IntPtr, ByVal data As StringByVal buf As IntegerByRef pcWritten As IntegerAs Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function EndPagePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function EndDocPrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      Public Shared Function SendStringToPrinter(ByVal printerName As StringByVal outputString As String)  
        Dim pBytes As IntPtr = Marshal.StringToCoTaskMemAnsi(outputString)  
        Dim dwCount As Integer = outputString.Length  
        Dim bSuccess As Boolean 
     
        bSuccess = SendBytesToPrinter(printerName, pBytes, dwCount)  
        Marshal.FreeCoTaskMem(pBytes)  
        Return bSuccess  
      End Function 
     
      Public Shared Function SendBytesToPrinter(ByVal printerName As StringByVal byteData As IntPtr, ByVal byteCount As Integer)  
        Dim dwError As Integer = 0  
        Dim dwWritten As Integer = 0  
        Dim hPrinter As IntPtr = New IntPtr(0)  
        Dim di As DOCINFO = New DOCINFO  
        Dim bSuccess As Boolean = False 
     
        di.pDocName = "Raw Document" 
        di.pDataType = "RAW" 
     
        If OpenPrinter(printerName, hPrinter, IntPtr.Zero) Then 
          If StartDocPrinter(hPrinter, 1, di) Then 
            If StartPagePrinter(hPrinter) Then 
              bSuccess = WritePrinter(hPrinter, byteData, byteCount, dwWritten)  
              EndPagePrinter(hPrinter)  
            End If 
            EndDocPrinter(hPrinter)  
          End If 
          ClosePrinter(hPrinter)  
        End If 
        If Not bSuccess Then dwError = Marshal.GetLastWin32Error  
        Return bSuccess  
      End Function 
     
      Public Shared Function SendFileToPrinter(ByVal printerName As StringByVal fileName As StringAs Boolean 
        Dim fs As FileStream = New FileStream(fileName, FileMode.Open)  
        Dim br As BinaryReader = New BinaryReader(fs)  
        Dim bytes() As Byte 
        Dim bSuccess As Boolean = False 
        ReDim bytes(fs.Length - 1)  
        Dim pUnmanagedBytes As IntPtr = New IntPtr(0)  
        Dim nLength As Integer 
     
        nLength = Convert.ToInt32(fs.Length)  
        bytes = br.ReadBytes(nLength)  
        pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength)  
        Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength)  
        bSuccess = SendBytesToPrinter(printerName, pUnmanagedBytes, nLength)  
        fs.Close()  
     
        Return bSuccess  
      End Function 
     
    End Class 

     Kind Regards,
      Mark
    Wednesday, January 7, 2009 9:29 AM

Answers

  • Thanks for the reply nobugz, although I've fixed it now. The problem was to do with the Ansi and Unicode declarations, I've also changed the "data" variable in WritePrinter to a Byte array.

    Below is the working code if anybody else needs/wants it.

    Imports System.Runtime  
    Imports System.Runtime.InteropServices  
    Imports System.IO  
    Imports System.Text.ASCIIEncoding  
     
    Public Structure DOCINFO  
      Dim pDocName As String 
      Dim pOutputFile As String 
      Dim pDataType As String 
    End Structure 
     
    ''' <summary>  
    '''   Printing Code  
    ''' </summary>  
    ''' <remarks>  
    '''   Converted from http://support.microsoft.com/kb/322091  
    ''' </remarks>  
    <ProgId("ByBoxInterop.RawPrinterHelper"), ClassInterface(ClassInterfaceType.None)> _  
    Public Class RawPrinterHelper  
     
      <DllImport("winspool.drv", CharSet:=CharSet.Ansi, ExactSpelling:=False, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function OpenPrinter(ByVal pPrinterName As StringByRef phPrinter As IntPtr, ByVal pDefault As IntegerAs Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Ansi, ExactSpelling:=False, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function StartDocPrinter(ByVal hPrinter As IntPtr, ByVal Level As IntegerByRef pDocInfo As DOCINFO) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function StartPagePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function WritePrinter(ByVal hPrinter As IntPtr, ByVal data() As ByteByVal buf As IntegerByRef pcWritten As IntegerAs Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function EndPagePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function EndDocPrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      Public Shared Function SendStringToPrinter(ByVal printerName As StringByVal outputString As String)  
        Dim bSuccess As Boolean 
        bSuccess = SendBytesToPrinter(printerName, ASCII.GetBytes(outputString))  
        Return bSuccess  
      End Function 
     
      Public Shared Function SendBytesToPrinter(ByVal printerName As StringByVal byteData() As Byte)  
        Dim dwError As Integer = 0  
        Dim dwWritten As Integer = 0  
        Dim hPrinter As IntPtr = New IntPtr(0)  
        Dim di As DOCINFO = New DOCINFO  
        Dim bSuccess As Boolean = False 
     
        di.pDocName = "Rawr Doc" 
        di.pDataType = "RAW" 
     
        If OpenPrinter(printerName, hPrinter, IntPtr.Zero) Then 
          If StartDocPrinter(hPrinter, 1, di) Then 
            If StartPagePrinter(hPrinter) Then 
              bSuccess = WritePrinter(hPrinter, byteData, byteData.Length, dwWritten)  
              EndPagePrinter(hPrinter)  
            End If 
            EndDocPrinter(hPrinter)  
          End If 
          ClosePrinter(hPrinter)  
        End If 
     
        If Not bSuccess Then dwError = Marshal.GetLastWin32Error  
        Return bSuccess  
      End Function 
     
      Public Shared Function SendFileToPrinter(ByVal printerName As StringByVal fileName As StringAs Boolean 
        Dim fs As FileStream = New FileStream(fileName, FileMode.Open)  
        Dim br As BinaryReader = New BinaryReader(fs)  
        Dim bytes() As Byte 
        Dim bSuccess As Boolean = False 
     
        ReDim bytes(fs.Length - 1)  
        bytes = br.ReadBytes(fs.Length)  
        bSuccess = SendBytesToPrinter(printerName, bytes)  
        fs.Close()  
     
        Return bSuccess  
      End Function 
     
    End Class 
     
    • Marked as answer by Mark Watkin Wednesday, January 7, 2009 11:12 AM
    Wednesday, January 7, 2009 11:12 AM

All replies

  • That's indeed the right P/Invoke to do this.  You are talking directly to the printer so you are never going to see anything like a printer icon.  Contact the printer manufacturer to find out what kind of control codes to send to the printer.
    Hans Passant.
    Wednesday, January 7, 2009 11:05 AM
    Moderator
  • Thanks for the reply nobugz, although I've fixed it now. The problem was to do with the Ansi and Unicode declarations, I've also changed the "data" variable in WritePrinter to a Byte array.

    Below is the working code if anybody else needs/wants it.

    Imports System.Runtime  
    Imports System.Runtime.InteropServices  
    Imports System.IO  
    Imports System.Text.ASCIIEncoding  
     
    Public Structure DOCINFO  
      Dim pDocName As String 
      Dim pOutputFile As String 
      Dim pDataType As String 
    End Structure 
     
    ''' <summary>  
    '''   Printing Code  
    ''' </summary>  
    ''' <remarks>  
    '''   Converted from http://support.microsoft.com/kb/322091  
    ''' </remarks>  
    <ProgId("ByBoxInterop.RawPrinterHelper"), ClassInterface(ClassInterfaceType.None)> _  
    Public Class RawPrinterHelper  
     
      <DllImport("winspool.drv", CharSet:=CharSet.Ansi, ExactSpelling:=False, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function OpenPrinter(ByVal pPrinterName As StringByRef phPrinter As IntPtr, ByVal pDefault As IntegerAs Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Ansi, ExactSpelling:=False, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function StartDocPrinter(ByVal hPrinter As IntPtr, ByVal Level As IntegerByRef pDocInfo As DOCINFO) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function StartPagePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function WritePrinter(ByVal hPrinter As IntPtr, ByVal data() As ByteByVal buf As IntegerByRef pcWritten As IntegerAs Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function EndPagePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function EndDocPrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      <DllImport("winspool.drv", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _  
      Public Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Long 
      End Function 
     
      Public Shared Function SendStringToPrinter(ByVal printerName As StringByVal outputString As String)  
        Dim bSuccess As Boolean 
        bSuccess = SendBytesToPrinter(printerName, ASCII.GetBytes(outputString))  
        Return bSuccess  
      End Function 
     
      Public Shared Function SendBytesToPrinter(ByVal printerName As StringByVal byteData() As Byte)  
        Dim dwError As Integer = 0  
        Dim dwWritten As Integer = 0  
        Dim hPrinter As IntPtr = New IntPtr(0)  
        Dim di As DOCINFO = New DOCINFO  
        Dim bSuccess As Boolean = False 
     
        di.pDocName = "Rawr Doc" 
        di.pDataType = "RAW" 
     
        If OpenPrinter(printerName, hPrinter, IntPtr.Zero) Then 
          If StartDocPrinter(hPrinter, 1, di) Then 
            If StartPagePrinter(hPrinter) Then 
              bSuccess = WritePrinter(hPrinter, byteData, byteData.Length, dwWritten)  
              EndPagePrinter(hPrinter)  
            End If 
            EndDocPrinter(hPrinter)  
          End If 
          ClosePrinter(hPrinter)  
        End If 
     
        If Not bSuccess Then dwError = Marshal.GetLastWin32Error  
        Return bSuccess  
      End Function 
     
      Public Shared Function SendFileToPrinter(ByVal printerName As StringByVal fileName As StringAs Boolean 
        Dim fs As FileStream = New FileStream(fileName, FileMode.Open)  
        Dim br As BinaryReader = New BinaryReader(fs)  
        Dim bytes() As Byte 
        Dim bSuccess As Boolean = False 
     
        ReDim bytes(fs.Length - 1)  
        bytes = br.ReadBytes(fs.Length)  
        bSuccess = SendBytesToPrinter(printerName, bytes)  
        fs.Close()  
     
        Return bSuccess  
      End Function 
     
    End Class 
     
    • Marked as answer by Mark Watkin Wednesday, January 7, 2009 11:12 AM
    Wednesday, January 7, 2009 11:12 AM