我想发送原始数据进行打印,避免选择打印机(快速打印)。
我正在尝试使用Microsoft提供的这个帮助程序:https://support.microsoft.com/en-us/kb/322091#top
然而,当我打电话给方法时:
RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, s);
我的打印机开始工作(产生一些噪音),但它从未拍摄白纸并开始打印。
我用我的两台打印机试过它,两台打印机的行为都是一样的。此外,我放弃了打印机坏了的可能性,因为我可以打印其他文件。
有什么不对?
答案 0 :(得分:3)
试试这个:
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class RawPrinterHelper
{
// Structure and API declarions:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
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.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)] 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 = "My C#.NET RAW Document";
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) )
{
// 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);
return bSuccess;
}
public static bool SendStringToPrinter( string szPrinterName, string szString )
{
IntPtr pBytes;
Int32 dwCount;
// How many characters are in the string?
// Fix from Nicholas Piasecki:
// dwCount = szString.Length;
dwCount = (szString.Length + 1) * Marshal.SystemMaxDBCSCharSize;
// 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;
}
}
答案 1 :(得分:1)
Fran_gg7,我最近遇到了同样的问题。首先,打开打印机上文档的持久性。这将允许您查看打印机是否成功接收到打印请求。
您将看到打印机队列中的项目,它们将保留在那里。
在我的方案中,打印请求被正确地发送到打印机,但是我在激光打印机上测试它,最终无法解释我传递给它的原始字符串数据。
我在标签打印机上测试了相同的输出,这个打印机可以理解我传递的ZPL(斑马编程语言)并且它的工作正常。
详细了解explanation
希望这有帮助。
答案 2 :(得分:1)
如果您正在使用此处https://support.microsoft.com/en-us/kb/322091#top的MSDN示例,但正在尝试使用字节数组而不是字符串或文件...这可能会有所帮助
public static void SendBytesToLocalPrinter(byte[] data, string printerName)
{
var size = Marshal.SizeOf(data[0]) * data.Length;
var pBytes = Marshal.AllocHGlobal(size);
try
{
SendBytesToPrinter(printerName, pBytes, size);
}
finally
{
Marshal.FreeCoTaskMem(pBytes);
}
}
这不会随字节数组编码而改变。如果您尝试发送一些utf8编码的字节序列并将一些二进制(即图像)数据混合在一起,这对我们的团队来说非常有用。
答案 3 :(得分:0)
如果使用" RawPrinterHelper"将纯文本打印到点阵。方法,它只适用于我手动添加打印机,选择Generic / Text Only,并选择分配给USB连接打印机的USB001端口(我测试中的okidata)。那么RawPrinterHelper.SendStringToPrinter的行为非常像lpt1的< lpd:'
答案 4 :(得分:0)
我的ZEBRA ZD420打印机出现了完全相同的问题。 将ZPL字符串发送给打印机时,仅数据指示灯会短暂闪烁而不进行打印。
我只改变了
Marshal.StringToCoTaskMemAnsi(szString);
to
Marshal.StringToCoTaskMemUTF8(szString);
它有效!