Solved

Print Report to Printer c#.

Posted on 2009-07-06
15
3,942 Views
Last Modified: 2016-05-20
I have the code below that renders my report from the Report Server 2008. Using visual studio to build a windows service.

The rendering works fine but flags an error: Error has occurred : Settings to access printer '\\wint0001\HPLaserJ' are not valid.

This printername is passed from another class.

If I don't set the printername, and use the default printer, the app always tries to use 'Send to OneNote' even though this isn't set as the default printer on the local machine?? Why is this? Doesn't the app use the same default printer as other windows apps? The default printer in windows is a netowrk printer, will this make a difference?

The report renders to onenote fine, but fails to the laser with the above error.

Ideally i'd like to use the default so when I run the windows service on another machine, the default printer on that machine is used and no code has to be modified.

Can anyone help?
using System;

using System.Drawing;

using System.Drawing.Imaging;

using System.Drawing.Printing;

using System.IO;

using System.Web.Services.Protocols;

using System.Runtime.InteropServices;

using BECScheduler.RS2005; // For Marshal.Copy

using BECScheduler.rsExecService;
 

namespace PrintReport

{

    /// <summary>

    /// A simple console application that demonstrates one way to

    /// print Reporting Services reports to a printer.

    /// </summary>

    
 

    class PrintExample

    {
 

        private byte[][] m_renderedReport;

        private Graphics.EnumerateMetafileProc m_delegate = null;

        private MemoryStream m_currentPageStream;

        private Metafile m_metafile = null;

        int m_numberOfPages;

        private int m_currentPrintingPage;

        private int m_lastPrintingPage;

        string _historyID = null;

        string extension = String.Empty;

        bool _forRendering = false;

        private BECScheduler.RS2005.ReportingService2005 rs;

        private BECScheduler.rsExecService.ReportExecutionService rsExec;
 

             public byte[][] RenderReport(string rptName,string sDate,string eDate)

        {

            // Private variables for rendering

            rs = new ReportingService2005();

            rsExec = new ReportExecutionService();

            rs.Credentials = new System.Net.NetworkCredential("administrator", "Holly678", "home.local");

            rsExec.Credentials = new System.Net.NetworkCredential("administrator", "Holly678", "home.local");

            rs.Url = "http://mail.mwint.co.uk/ReportServer_mssql2008/ReportService2005.asmx";

            rsExec.Url = "http://mail.mwint.co.uk/ReportServer_mssql2008/ReportExecution2005.asmx";

            string deviceInfo = null;

            string format = "IMAGE";

            Byte[] firstPage = null;

            string encoding;

            string mimeType;

            BECScheduler.rsExecService.Warning[] warnings = null;

            BECScheduler.RS2005.ParameterValue[] reportHistoryParameters = null;

            string[] streamIDs = null;

            Byte[][] pages = null;

            string historyID = null; 
 

            // Build device info based on the start page

            deviceInfo =

               String.Format(@"<DeviceInfo><OutputFormat>{0}</OutputFormat></DeviceInfo>", "emf");

            BECScheduler.RS2005.ParameterValue[] _values = null;

            BECScheduler.RS2005.DataSourceCredentials[] _credentials = null;

            BECScheduler.RS2005.ReportParameter[] _parameters = null;
 
 

            //Exectute the report and get page count.

            try

            {

                _parameters = rs.GetReportParameters(rptName, _historyID, _forRendering, _values, _credentials);

                BECScheduler.rsExecService.ExecutionInfo ei = rsExec.LoadReport(rptName, historyID);

                BECScheduler.rsExecService.ParameterValue[] parameters = new BECScheduler.rsExecService.ParameterValue[2];

                // Renders the first page of the report and returns streamIDs for 

                // subsequent pages

                if (_parameters.Length > 0)

                {

                    parameters[0] = new BECScheduler.rsExecService.ParameterValue();

                    parameters[0].Label = "";

                    parameters[0].Name = "SDate";

                    parameters[0].Value = sDate;

                    parameters[1] = new BECScheduler.rsExecService.ParameterValue();

                    parameters[1].Label = "";

                    parameters[1].Name = "EDate";

                    parameters[1].Value = eDate;

                }

                rsExec.SetExecutionParameters(parameters, "en-GB");
 
 

                firstPage = rsExec.Render(format, deviceInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
 

                // The total number of pages of the report is 1 + the streamIDs         

                m_numberOfPages = streamIDs.Length + 1;

                pages = new Byte[m_numberOfPages][];
 

                // The first page was already rendered

                pages[0] = firstPage;
 

                for (int pageIndex = 1; pageIndex < m_numberOfPages; pageIndex++)

                {

                    // Build device info based on start page

                    deviceInfo =

                       String.Format(@"<DeviceInfo><OutputFormat>{0}</OutputFormat><StartPage>{1}</StartPage></DeviceInfo>",

                         "emf", pageIndex + 1);

                    pages[pageIndex] = rsExec.Render(format, deviceInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);

                }

            }
 

            catch (SoapException ex)

            {

                new BEC.Logger.Logger().ErrorLog(ex.Message);

            }
 

            catch (Exception ex)

            {

                new BEC.Logger.Logger().ErrorLog(ex.Message);

            }
 

            finally

            {

                Console.WriteLine("Number of pages: {0}", pages.Length);

            }
 

            return pages;

        }
 
 

        public bool PrintReport(string printerName,string rptName,string sDate,string eDate)

        {

            this.RenderedReport = this.RenderReport(rptName,sDate,eDate);

            try

            {

                // Wait for the report to completely render.

                if (m_numberOfPages < 1)

                    return false;

                PrinterSettings printerSettings = new PrinterSettings();

                printerSettings.MaximumPage = m_numberOfPages;

                printerSettings.MinimumPage = 1;

                printerSettings.PrintRange = PrintRange.SomePages;

                printerSettings.FromPage = 1;

                printerSettings.ToPage = m_numberOfPages;

                printerSettings.PrinterName = printerName;

                printerSettings.DefaultPageSettings.Landscape = false;

                

                PrintDocument pd = new PrintDocument();

                m_currentPrintingPage = 1;

                m_lastPrintingPage = m_numberOfPages;

                pd.PrinterSettings = printerSettings;
 

                // Print report

                new BEC.Logger.Logger().StatusLog("Printing Report....");

                pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);

                pd.Print();

            }
 

            catch (Exception ex)

            {

                new BEC.Logger.Logger().ErrorLog(ex.Message);

            }

            finally

            {

                // Clean up goes here.

            }
 

            return true;

        }
 

        private void pd_PrintPage(object sender, PrintPageEventArgs ev)

        {

            ev.HasMorePages = false;

            if (m_currentPrintingPage <= m_lastPrintingPage && MoveToPage(m_currentPrintingPage))

            {

                // Draw the page

                ReportDrawPage(ev.Graphics);

                // If the next page is less than or equal to the last page, 

                // print another page.

                if (++m_currentPrintingPage <= m_lastPrintingPage)

                    ev.HasMorePages = true;

            }

        }
 

        // Method to draw the current emf memory stream 

        private void ReportDrawPage(Graphics g)

        {

            if (null == m_currentPageStream || 0 == m_currentPageStream.Length || null == m_metafile)

                return;

            lock (this)

            {

                // Set the metafile delegate.

                int width = m_metafile.Width;

                int height = m_metafile.Height;

                m_delegate = new Graphics.EnumerateMetafileProc(MetafileCallback);

                // Draw in the rectangle

                Point destPoint = new Point(0, 0);

                g.EnumerateMetafile(m_metafile, destPoint, m_delegate);

                // Clean up

                m_delegate = null;

            }

        }
 

        private bool MoveToPage(Int32 page)

        {

            // Check to make sure that the current page exists in

            // the array list

            if (null == this.RenderedReport[m_currentPrintingPage - 1])

                return false;

            // Set current page stream equal to the rendered page

            m_currentPageStream = new MemoryStream(this.RenderedReport[m_currentPrintingPage - 1]);

            // Set its postion to start.

            m_currentPageStream.Position = 0;

            // Initialize the metafile

            if (null != m_metafile)

            {

                m_metafile.Dispose();

                m_metafile = null;

            }

            // Load the metafile image for this page

            m_metafile = new Metafile((Stream)m_currentPageStream);

            return true;

        }
 

        private bool MetafileCallback(

           EmfPlusRecordType recordType,

           int flags,

           int dataSize,

           IntPtr data,

           PlayRecordCallback callbackData)

        {

            byte[] dataArray = null;

            // Dance around unmanaged code.

            if (data != IntPtr.Zero)

            {

                // Copy the unmanaged record to a managed byte buffer 

                // that can be used by PlayRecord.

                dataArray = new byte[dataSize];

                Marshal.Copy(data, dataArray, 0, dataSize);

            }

            // play the record.      

            m_metafile.PlayRecord(recordType, flags, dataSize, dataArray);
 

            return true;

        }
 

        public byte[][] RenderedReport

        {

            get

            {

                return m_renderedReport;

            }

            set

            {

                m_renderedReport = value;

            }

        }

    }

}

Open in new window

0
Comment
Question by:wint100
  • 8
  • 7
15 Comments
 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 500 total points
ID: 24787915
Your service runs as a particular user; what user is your service configured to run as, and what is that users default printer?
0
 
LVL 1

Author Comment

by:wint100
ID: 24787954
The Service Installer set the service to logon using Localsystem. Is this what you mean?
0
 
LVL 33

Accepted Solution

by:
Todd Gerbert earned 500 total points
ID: 24787995
Yes.  My point is that the default printer selection is a per-user setting; if you logon to the computer and set your default printer it's not going to affect *my* default printer, nor is it going to set any other users' default printer - including the user named LocalService.  Therefore, what you see in your printers folder is meaningless to your service.

I would implement a configuration file, and/or a simple GUI to change the config file, and let the admin pick the name of the printer from a list of available choices.
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 24788005
I implemented a similar setup by creating a user, then configuring the service to run as that user.  Then I can log onto the workstation as that user and setup printer preferences.  I don't know if you can change such things for the LocalService user.
0
 
LVL 1

Author Comment

by:wint100
ID: 24788111
I've attached my app.config below, how can this be modified to set the user?
<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <configSections>

        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >

            <section name="BECScheduler.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />

        </sectionGroup>

    </configSections>

    <system.serviceModel>

        <bindings />

        <client />

    </system.serviceModel>

    <applicationSettings>

         <BECScheduler.Properties.Settings>

            <setting name="BECScheduler_RS2005_ReportingService2005" serializeAs="String">

                <value>http://OMEGA:80/ReportServer_MSSQL2008/ReportService2005.asmx</value>

            </setting>

            <setting name="BECScheduler_rsExecService_ReportExecutionService"

                serializeAs="String">

                <value>http://OMEGA:80/ReportServer_MSSQL2008/ReportExecution2005.asmx</value>

            </setting>

                

        </BECScheduler.Properties.Settings>

    </applicationSettings>

</configuration>

Open in new window

0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 24788136
You don't.  You change your Service Installer.  You can also have a look in the Services MMC Snap-In (Right-click My Computer, choose Manage, then navigate to Services in the left-hand pane).
0
 
LVL 1

Author Comment

by:wint100
ID: 24788150
I've tried doing that so it logs on as the domain administrator, but the same error appeared when setting the printername to the network printer.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 24788181
Log onto the computer as the domain administrator.  Connect to that network printer and print a test page.  Now test your service.
0
 
LVL 1

Author Comment

by:wint100
ID: 24788434
Tried that and the default printer is still 'send to onenote'.
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 24788523
Did you set that networked printer as default?  Are you sure you're logging onto the computer using the same user your service is?
0
 
LVL 1

Author Comment

by:wint100
ID: 24788551
I did yes, i'm just checking the code to make sure i tlogs on as the domain account. When installed the service still says it logs on using local system account with Allow Interact with Desktop ticked.

Code below:


namespace BECScheduler

{

    using System;

    using System.ComponentModel;

    using System.Configuration.Install;

    using System.ServiceProcess;

    using System.Threading;

    using System.Timers;

    using BEC.ProcessScheduler;
 

    [RunInstaller(true)]

    public class ProjectInstaller : Installer

    {

        private Container components = null;

        private ServiceInstaller serviceInstaller1;

        private ServiceProcessInstaller serviceProcessInstaller1;
 

        public ProjectInstaller()

        {

            this.InitializeComponent();

        }
 

        protected override void Dispose(bool disposing)

        {

            if (disposing && (this.components != null))

            {

                this.components.Dispose();

            }

            base.Dispose(disposing);

        }
 

        private void InitializeComponent()

        {

            this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();

            this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();

            // 

            // serviceProcessInstaller1

            // 

            this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;

            this.serviceProcessInstaller1.Password = "password";

            this.serviceProcessInstaller1.Username = "domain/user";

            // 

            // serviceInstaller1

            // 

            this.serviceInstaller1.DisplayName = "BECScheduler";

            this.serviceInstaller1.ServiceName = "BECScheduler";

            this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;

            this.serviceInstaller1.AfterInstall += new System.Configuration.Install.InstallEventHandler(this.serviceInstaller1_AfterInstall);

            // 

            // ProjectInstaller

            // 

            this.Installers.AddRange(new System.Configuration.Install.Installer[] {

            this.serviceProcessInstaller1,

            this.serviceInstaller1});
 

        }
 

        private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)

        {

            CreateMethod method = new CreateMethod();

            new Thread(new ThreadStart(method.Callmethod)).Start();

        }

    }

}

Open in new window

0
 
LVL 1

Author Comment

by:wint100
ID: 24788607
changed the username to "domain\\user" but still no joy.
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 24788651
Try opening the services control panel and changing it manually, tackle one problem at a time.

0
 
LVL 1

Author Comment

by:wint100
ID: 24788758
Success when entering the logon user manually. It doesn't allow me to select interact with desktop though. Is this a limitation.

Any idea why my code won't let me set the user from the installer.
            this.serviceProcessInstaller1.Password = "Holly678";

            this.serviceProcessInstaller1.Username = "Mark Wint@Home.local";

            this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;

Open in new window

0
 
LVL 1

Author Comment

by:wint100
ID: 24789260
USed this articel to imperonsate the user running the code:

http://www.codeproject.com/KB/cs/zetaimpersonator.aspx

Works a treat. Thanks!
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Introduction Earlier I wrote an article about the new lookup functions (http://www.experts-exchange.com/A_3433.html) that ship with SQL Server 2008 R2.  In this article I’m going to show you another new feature of SSRS 2008 R2, this time in the vis…
It is helpful to note: This is a cosmetic update and is not required, but should help your reports look better for your boss.  This issue has manifested itself in SSRS version 3.0 is where I have seen this behavior in.  And this behavior is only see…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now