2015-04-03 5 views
1

Я использую код, который я нашел в Интернете, который был решением чужой подобной проблемы с печатью. Кажется, что код работает нормально и даже ошибки, когда я ожидаю его (например, когда я целенаправленно вхожу в плохое имя принтера). Проблема, с которой я сталкиваюсь, заключается в том, что вызов interop для метода WritePrinter от winspool.drv не приводит к тому, что принтер печатает что-либо, даже если этот метод возвращает «true». Любые идеи, почему принтер на самом деле не печатает ???C# winspool.drv call to WritePrinter не печатает

public class PrintRaw 
    { 
     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
     public class DOC_INFO_1 
     { 
      [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.Ansi, 
      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.Ansi, 
      ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
     public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, 
                [In, MarshalAs(UnmanagedType.LPStruct)] DOC_INFO_1 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); 

     public void Print(String printerName, String filename) 
     { 
      IntPtr lhPrinter; 
      OpenPrinter(printerName, out lhPrinter, new IntPtr(0)); 

      if (lhPrinter.ToInt32() == 0) 
       return; //Printer not found!! 

      var rawPrinter = new DOC_INFO_1() { pDocName = "My Document", pDataType = "RAW" }; 

      StartDocPrinter(lhPrinter, 1, rawPrinter); 

      using (var b = new BinaryReader(File.Open(filename, FileMode.Open))) 
      { 
       var length = (int)b.BaseStream.Length; 
       const int bufferSize = 8192; 

       var numLoops = length/bufferSize; 
       var leftOver = length % bufferSize; 


       for (int i = 0; i < numLoops; i++) 
       { 
        var buffer = new byte[bufferSize]; 
        int dwWritten; 

        b.Read(buffer, 0, bufferSize); 
        IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length); 
        Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length); 
        WritePrinter(lhPrinter, unmanagedPointer, bufferSize, out dwWritten); 
        Marshal.FreeHGlobal(unmanagedPointer); 
       } 

       if (leftOver > 0) 
       { 
        var buffer = new byte[leftOver]; 
        int dwWritten; 

        b.Read(buffer, 0, leftOver); 
        IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length); 
        Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length); 
        var result = WritePrinter(lhPrinter, unmanagedPointer, leftOver, out dwWritten); 
        Marshal.FreeHGlobal(unmanagedPointer); 
       } 
      } 

      EndDocPrinter(lhPrinter); 
      ClosePrinter(lhPrinter); 
     } 
    } 
+0

MSDN говорит эти функции находятся в spoolss.dll –

+0

Вызовы вызываются, и он даже возвращает дескриптор принтера, когда я даю ему настоящее имя принтера, поэтому я не думаю, что это проблема. Как я упоминал в вопросе, он даже терпит неудачу, когда я даю ему плохое имя принтера. Плюс большая часть этого кода от самого MSDN – spoof3r

+1

В случае, если кому-то интересно, код взят со следующей ссылки. Я верю: https://vishalsbsinha.wordpress.com/2014/05/06/how-to-programmatically-c -net-print-a-pdf-file-direct-to-printer – slayernoah

ответ

0

Изменить код так:

var rawPrinter = new DOC_INFO_1() { pDocName = "My Document", pDataType = "Text" }; 
0

Вам нужно позвонить StartPagePrinter после StartDocPrinter и перед WritePrinter

0
[DllImport("winspool.drv", EntryPoint = "FlushPrinter", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
public static extern bool FlushPrinter(IntPtr hPrinter, IntPtr pBuf, Int32 cbBuf, out Int32 pcWritten, Int32 cSleep); 

WritePrinter(lhPrinter, unmanagedPointer, bufferSize, out dwWritten); 

после оных:

FlushPrinter(hPrinter, pBytes, dwCount, out dwWritten,2); 
+1

Возможно, вам придется объяснить свой ответ и использовать форматирование текста. –