Printing a Report Server-Side and Silently
Asked Answered
F

3

5

I am trying to write a program that allows me to print a ssrs report(.rdl file) from the server-side code to a predetermined printer without any pop ups asking me which printer I want to use can this be done?

Fere answered 15/3, 2012 at 10:15 Comment(4)
What kind of report is it? The question is impossible to answer generally, we need to know what kind of report it is. Please tag appropriately.Diamine
Sorry ssrs report like an .rdl fileFere
Just to clarify - the printer is on the same network as your server, and not your client?Prosody
Yes the client server and printer are all on the same networkFere
E
5

EDIT
Also pasted the code for the ReportViewerDisposer implementation I'm using.

Together with the class ReportViewerDisposer found here I'm using the following code, which is part of a larger project, but you should be able to adapt it easily:

private string m_printerName;
private string m_server;
private string m_path;
private string m_name;
private Dictionary<string, string> 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<Stream> 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<ReportParameter> param = new List<ReportParameter>();
    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(
      "<DeviceInfo>" +
      "  <OutputFormat>EMF</OutputFormat>" +
      "  <PageWidth>{0}cm</PageWidth>" +
      "  <PageHeight>{1}cm</PageHeight>" +
      "  <MarginTop>{2}cm</MarginTop>" +
      "  <MarginLeft>{3}cm</MarginLeft>" +
      "  <MarginRight>{4}cm</MarginRight>" +
      "  <MarginBottom>{5}cm</MarginBottom>" +
      "</DeviceInfo>",
      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<Stream>();
    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;
    }
    }
} 
Emmet answered 15/3, 2012 at 10:29 Comment(7)
Ok, the code in the link you sent me is using NewLateBinding which uses namespace Microsoft.VisualBasic.CompilerServices which I cannot find a reference for could you let me know what you are referencing so I can test your codeFere
I added the ReportViewerDisposer to my answer.Emmet
Ok, we are getting somewhere now I assume all the m_* and PrintPage are all class variables and while I can figure out some of them there is some ambiguity in my mind as to what a couple of them areFere
Added variable declarations as well.Emmet
Ok, got some empty event handlers for the PrintPage and QueryPageSettings and its printing a blank page and is getting all the parameters for the report this is excellent but I am not getting the report coming out of the printer just a blank sheet I think I need to add to the printpage event handler at least I tried using code from a different site to get this working and it printed out random text instead of the reportFere
Sorry, forgot the code for the two events. I inserted them in my answer.Emmet
Thank you this worked perfectly its nice to have a full solution all in one.Fere
O
2

First of all you need to render your SSRS report into PDF format and then you can print the PDF file directly without opening any popup, Refer to code below:

    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);

    /// <summary>
    /// This function gets the pdf file name.
    /// This function opens the pdf file, gets all its bytes & send them to print.
    /// </summary>
    /// <param name="szPrinterName">Printer Name</param>
    /// <param name="szFileName">Pdf File Name</param>
    /// <returns>true on success, false on failure</returns>
    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);
        }
    }

    /// <summary>
    /// This function gets the printer name and an unmanaged array of bytes, the function sends those bytes to the print queue.
    /// </summary>
    /// <param name="szPrinterName">Printer Name</param>
    /// <param name="pBytes">No. of bytes in the pdf file</param>
    /// <param name="dwCount">Word count</param>
    /// <returns>True on success, false on failure</returns>
    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
Oquassa answered 22/7, 2015 at 12:38 Comment(0)
D
0
  1. First add a Web reference to the Reporting Services Web service in your development project that points to your report server. This can be done by right-clicking on your project in Visual Studio and choosing Add Web reference... . You should add a reference to a local report server (localhost) at "http://localhost/reportserver/reportservice.asmx".
  2. Use the ReportingService class to do printing using some steps.

follow this.

Reference links:
Automatically print SSRS report?
SSRS Printing without showind Print Dialog
Printing Reports Programmatically Using C# and SQL Server 2000 Reporting Services Print SSRS Report Automatically
Printing Reporting Services 2005 Reports

Delivery answered 15/3, 2012 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.