Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing a Report Server-Side and Silently

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?

like image 792
user1271242 Avatar asked Mar 15 '12 10:03

user1271242


2 Answers

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;
    }
    }
} 
like image 114
Thorsten Dittmar Avatar answered Nov 15 '22 06:11

Thorsten Dittmar


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
like image 40
Pramod Jaiswal Avatar answered Nov 15 '22 05:11

Pramod Jaiswal