我的服务使用以下代码将报告转换为字节数组,然后传递给客户端(wpf应用):
byte[] bytes = renderer.ServerReport.Render("PDF", deviceInfo, out mimeType, out encoding, out extension, out streamids, out warnings);
其中renderer是Microsoft.Reporting.Webforms.ReportViewer的实例.这里有一个问题:encoding输出参数返回null,因此找不到有关编码的信息.
UI必须将此字节数组以静默方式打印到打印机.可以将此字节数组直接发送到打印机,而不是在UI中将其转换回PDF文件然后进行打印吗?
在查看msdn链接后,我实际上尝试了以下类似操作,但是当实际报告只有一页或一页时,这会在许多页面上打印出奇怪的符号.有关winspool dll的在线功能的信息较少,所以不确定我要去哪里.
任何想法高度赞赏.
public class RawPrintHelper
{
//Structure and API declarions:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
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 = "OpenPrinter", SetLastError = true, CharSet = CharSet.Auto, 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 = "StartDocPrinter", SetLastError = true, CharSet = CharSet.Auto, 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;
}
}
解决方法:
是的,这行不通.您使用此代码绕过打印机驱动程序,必须使用所用特定打印机的打印机控制语言来生成打印命令. PCL和Postscript是常见的打印机控制语言.但不管怎么说,制造商通常会创建自己的自定义品种.
看来您正在发送PDF,但我不知道任何使用PDF作为其本机控制语言的打印机.也许存在这样的打印机,显然您没有.我真的无法猜测为什么您会在服务中使用Webforms类,很难提供替代方法.从服务进行打印通常不是一个好主意,打印机驱动程序太高兴了,无法显示“尽快更换碳粉”提示.显示在不可见的桌面上,您无法找出为什么无法打印文档.