以静默方式打印报表服务器端

我正在尝试编写一个程序,允许我从服务器端代码打印ssrs报告(.rdl文件)到预定的打印机,而没有任何弹出窗口询问我想要使用哪台打印机可以这样做吗?

编辑
还粘贴了我正在使用的ReportViewerDisposer实现的代码。

与我在这里找到的类ReportViewerDisposer一起使用以下代码,它是更大项目的一部分,但您应该能够轻松地进行调整:

 private string m_printerName; private string m_server; private string m_path; private string m_name; private Dictionary m_parameters; private SizeF m_pageSize; private float m_marginLeft; private float m_marginTop; private float m_marginRight; private float m_marginBottom; private short m_copies; private int m_currentPageIndex; private List m_reportStreams; public void PrintReport() { string mime, extension; ReportViewer viewer = new ReportViewer(); ReportViewerDisposer disposer = new ReportViewerDisposer(viewer); try { viewer.ProcessingMode = ProcessingMode.Remote; viewer.ServerReport.ReportServerUrl = new Uri(String.Format("http://{0}/ReportServer", m_server)); viewer.ServerReport.ReportPath = String.Format("/{0}/{1}", m_path, m_name); List param = new List(); foreach (ReportParameterInfo paramInfo in viewer.ServerReport.GetParameters()) { if (m_parameters.ContainsKey(paramInfo.Name.ToUpperInvariant())) { string value = m_parameters[paramInfo.Name.ToUpperInvariant()]; param.Add(new ReportParameter(paramInfo.Name, value)); } } viewer.ServerReport.SetParameters(param); viewer.RefreshReport(); CultureInfo us = new CultureInfo("en-US"); string deviceInfo = String.Format( "" + " EMF" + " {0}cm" + " {1}cm" + " {2}cm" + " {3}cm" + " {4}cm" + " {5}cm" + "", Math.Round(m_pageSize.Width, 2).ToString(us), Math.Round(m_pageSize.Height, 2).ToString(us), Math.Round(m_marginTop, 2).ToString(us), Math.Round(m_marginLeft, 2).ToString(us), Math.Round(m_marginRight, 2).ToString(us), Math.Round(m_marginBottom, 2).ToString(us)); m_reportStreams = new List(); try { NameValueCollection urlAccessParameters = new NameValueCollection(); urlAccessParameters.Add("rs:PersistStreams", "True"); Stream s = viewer.ServerReport.Render("IMAGE", deviceInfo, urlAccessParameters, out mime, out extension); m_reportStreams.Add(s); urlAccessParameters.Remove("rs:PersistStreams"); urlAccessParameters.Add("rs:GetNextStream", "True"); do { s = viewer.ServerReport.Render("IMAGE", deviceInfo, urlAccessParameters, out mime, out extension); if (s.Length != 0) m_reportStreams.Add(s); } while (s.Length > 0); DoPrint(); } finally { foreach (Stream s in m_reportStreams) { s.Close(); s.Dispose(); } m_reportStreams = null; } } finally { disposer.CollectGarbageOnDispose = true; disposer.Dispose(); } } private void DoPrint() { m_currentPageIndex = 0; PrintDocument printDoc = new PrintDocument(); try { printDoc.PrintController = new StandardPrintController(); printDoc.PrinterSettings.PrinterName = m_printerName; printDoc.PrinterSettings.Copies = m_copies; if (!printDoc.PrinterSettings.IsValid) { throw new ArgumentException(String.Format("Drucker '{0}' ist nicht gültig!", m_printerName)); } // Drucke das Dokument aus printDoc.PrintPage += new PrintPageEventHandler(PrintPage); printDoc.QueryPageSettings += new QueryPageSettingsEventHandler(QueryPageSettings); printDoc.Print(); } finally { printDoc.PrintPage -= new PrintPageEventHandler(PrintPage); printDoc.QueryPageSettings -= new QueryPageSettingsEventHandler(QueryPageSettings); printDoc.Dispose(); } } private void PrintPage(object sender, PrintPageEventArgs ev)    { if (m_currentPageIndex < m_reportStreams.Count) { Metafile mf = new Metafile(m_reportStreams[m_currentPageIndex++]); try { ev.Graphics.DrawImage(mf, ev.PageBounds); } finally { mf.Dispose(); } } ev.HasMorePages = m_currentPageIndex < m_reportStreams.Count; } private void QueryPageSettings(object sender, QueryPageSettingsEventArgs e) { e.PageSettings.Landscape = m_pageSize.Width > m_pageSize.Height; } private class ReportViewerDisposer : IDisposable { // Fields private bool _CollectGarbageOnDispose = true; private ReportViewer _ReportViewer; private bool disposedValue = false; private const string EVENTHANDLER_ON_USER_PREFERENCE_CHANGED = "OnUserPreferenceChanged"; private const string LIST_HANDLERS = "_handlers"; private const string ON_USER_PREFERENCE_CHANGED_EVENT = "OnUserPreferenceChangedEvent"; private const string SYSTEM_EVENT_INVOKE_INFO = "SystemEventInvokeInfo"; private const string TARGET_DELEGATE = "_delegate"; private const string TOOLSTRIP_CONTROL_NAME = "reportToolBar"; private const string TOOLSTRIP_TEXTBOX_CONTROL_NAME_CURRENT_PAGE = "currentPage"; private const string TOOLSTRIP_TEXTBOX_CONTROL_NAME_TEXT_TO_FIND = "textToFind"; // Methods public ReportViewerDisposer(ReportViewer rptv) { if (rptv == null) { throw new ArgumentNullException("ReportViewer cannot be null."); } this._ReportViewer = rptv; } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!this.disposedValue && disposing) { this.TearDownReportViewer(); this._ReportViewer.Dispose(); if (this._CollectGarbageOnDispose) { GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } } this.disposedValue = true; } private void NullRefOnUserPreferenceChanged(object o, string field) { try { FieldInfo fi = o.GetType().GetField(field, BindingFlags.NonPublic | BindingFlags.Instance); if (fi != null) { int i; ToolStripTextBox tb = (ToolStripTextBox)fi.GetValue(o); object tbc = tb.Control; Delegate d = Delegate.CreateDelegate(typeof(UserPreferenceChangedEventHandler), tbc, EVENTHANDLER_ON_USER_PREFERENCE_CHANGED); object handlers = typeof(SystemEvents).GetField(LIST_HANDLERS, BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); object upcHandler = typeof(SystemEvents).GetField(ON_USER_PREFERENCE_CHANGED_EVENT, BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); object systemEventInvokeInfo = typeof(SystemEvents).GetNestedType(SYSTEM_EVENT_INVOKE_INFO, BindingFlags.NonPublic | BindingFlags.Instance); IList upcHandlerList = (IList)((IDictionary)handlers)[upcHandler]; int targetCount = 0; for (i = 0; i < upcHandlerList.Count; i++) { systemEventInvokeInfo = upcHandlerList[i]; Delegate target = (Delegate)systemEventInvokeInfo.GetType().GetField(TARGET_DELEGATE, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(systemEventInvokeInfo); if (target.Target == d.Target) { targetCount++; } } for (i = 1; i <= targetCount; i++) { SystemEvents.UserPreferenceChanged -= ((UserPreferenceChangedEventHandler)d); } } } catch { } } private void TearDownReportViewer() { FieldInfo fi = this._ReportViewer.GetType().GetField(TOOLSTRIP_CONTROL_NAME, BindingFlags.NonPublic | BindingFlags.Instance); if (fi != null) { object o = fi.GetValue(this._ReportViewer); this.NullRefOnUserPreferenceChanged(o, TOOLSTRIP_TEXTBOX_CONTROL_NAME_CURRENT_PAGE); this.NullRefOnUserPreferenceChanged(o, TOOLSTRIP_TEXTBOX_CONTROL_NAME_TEXT_TO_FIND); } } // Properties public bool CollectGarbageOnDispose { get { return this._CollectGarbageOnDispose; } set { this._CollectGarbageOnDispose = value; } } } 

首先,您需要将SSRS报告呈现为PDF格式,然后您可以直接打印PDF文件而无需打开任何弹出窗口,请参阅下面的代码:

  public void PrintPreviewSSRSReport(string reportName) { try { string reportPath = string.Empty; string historyID = null; string deviceInfo = null; string extension = null; string encoding = null; string mimeType = null; string[] streamIDs = null; string format = "PDF"; Byte[] result; ReportExecution2005.Warning[] warnings = null; ExecutionInfo execInfo = new ExecutionInfo(); TrustedUserHeader trusteduserHeader = new TrustedUserHeader(); ExecutionHeader execHeader = new ExecutionHeader(); ServerInfoHeader serviceInfo = new ServerInfoHeader(); MHTools.ReportExecution2005.ReportParameter[] _parameters = null; ParameterValue[] _ParameterValue = null; //Set the report path reportPath = "/Reports/SalesReport"; //Create the object of report execution web service ReportExecutionServiceSoapClient rsExec = new ReportExecutionServiceSoapClient(); //Use this if you don't need to pass the credentials from code rsExec.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation; //Load the reports rsExec.LoadReport(trusteduserHeader, reportPath, historyID, out serviceInfo, out execInfo); execHeader.ExecutionID = execInfo.ExecutionID; //Get the parameters details from load report and eet the value in paremeters if any _parameters = execInfo.Parameters; _ParameterValue = new ParameterValue[1]; _ParameterValue[0] = new ParameterValue(); _ParameterValue[0].Name = _parameters[0].Name; _ParameterValue[0].Value = "12345"; //Set the parameters rsExec.SetExecutionParameters(execHeader, null, _ParameterValue, "en-us", out execInfo); //Render the report rsExec.Render(execHeader, null, format, deviceInfo, out result, out extension, out mimeType, out encoding, out warnings, out streamIDs); //pass the file path where pdf file will be saved using (FileStream stream = File.OpenWrite(PDFFile)) { stream.Write(result, 0, result.Length); } //send the padf file path to printer SendFileToPrinter(PDFFile); } catch (Exception ex) { // } } #region Print SSRS Report [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] private 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)] private 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)] private static extern bool ClosePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] private 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)] private static extern bool EndDocPrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] private static extern bool StartPagePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] private static extern bool EndPagePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] private static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten); [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int size); ///  /// This function gets the pdf file name. /// This function opens the pdf file, gets all its bytes & send them to print. ///  /// Printer Name /// Pdf File Name /// true on success, false on failure public bool SendFileToPrinter(string pdfFileName) { try { #region Get Connected Printer Name PrintDocument pd = new PrintDocument(); StringBuilder dp = new StringBuilder(256); int size = dp.Capacity; if (GetDefaultPrinter(dp, ref size)) { pd.PrinterSettings.PrinterName = dp.ToString().Trim(); } #endregion Get Connected Printer Name // Open the PDF file. FileStream fs = new FileStream(pdfFileName, FileMode.Open); // Create a BinaryReader on the file. BinaryReader br = new BinaryReader(fs); Byte[] bytes = new Byte[fs.Length]; bool success = false; // Unmanaged pointer. IntPtr ptrUnmanagedBytes = new IntPtr(0); int nLength = Convert.ToInt32(fs.Length); // Read contents of the file into the array. bytes = br.ReadBytes(nLength); // Allocate some unmanaged memory for those bytes. ptrUnmanagedBytes = Marshal.AllocCoTaskMem(nLength); // Copy the managed byte array into the unmanaged array. Marshal.Copy(bytes, 0, ptrUnmanagedBytes, nLength); // Send the unmanaged bytes to the printer. success = SendBytesToPrinter(pd.PrinterSettings.PrinterName, ptrUnmanagedBytes, nLength); // Free the unmanaged memory that you allocated earlier. Marshal.FreeCoTaskMem(ptrUnmanagedBytes); return success; } catch (Exception ex) { throw new Exception(ex.Message); } } ///  /// This function gets the printer name and an unmanaged array of bytes, the function sends those bytes to the print queue. ///  /// Printer Name /// No. of bytes in the pdf file /// Word count /// True on success, false on failure private bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount) { try { Int32 dwError = 0, dwWritten = 0; IntPtr hPrinter = new IntPtr(0); DOCINFOA di = new DOCINFOA(); bool success = false; // Assume failure unless you specifically succeed. di.pDocName = Path.GetFileNameWithoutExtension(PDFFile); 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 the bytes. success = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); EndPagePrinter(hPrinter); } EndDocPrinter(hPrinter); } ClosePrinter(hPrinter); } // If print did not succeed, GetLastError may give more information about the failure. if (success == false) { dwError = Marshal.GetLastWin32Error(); } return success; } catch (Exception ex) { throw new Exception(ex.Message); } } #endregion 
  1. 首先在开发项目中为指向报表服务器的Reporting Services Web服务添加Web引用。 这可以通过在Visual Studio中右键单击项目并选择“添加Web引用…”来完成。 您应该在“ http://localhost/reportserver/reportservice.asmx ”中添加对本地报表服务器(localhost)的引用。
  2. 使用ReportingService类使用某些步骤进行打印。

按照这个 。

参考链接:
自动打印SSRS报告?
没有showind打印对话框的SSRS打印
使用C#和SQL Server 2000 Reporting Services以编程方式打印报表
自动打印SSRS报告
打印Reporting Services 2005报告