Print Report to Printer c#.

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

LVL 1
wint100Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Todd GerbertIT ConsultantCommented:
Your service runs as a particular user; what user is your service configured to run as, and what is that users default printer?
0
wint100Author Commented:
The Service Installer set the service to logon using Localsystem. Is this what you mean?
0
Todd GerbertIT ConsultantCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Become a CompTIA Certified Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

Todd GerbertIT ConsultantCommented:
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
wint100Author Commented:
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
Todd GerbertIT ConsultantCommented:
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
wint100Author Commented:
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
Todd GerbertIT ConsultantCommented:
Log onto the computer as the domain administrator.  Connect to that network printer and print a test page.  Now test your service.
0
wint100Author Commented:
Tried that and the default printer is still 'send to onenote'.
0
Todd GerbertIT ConsultantCommented:
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
wint100Author Commented:
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
wint100Author Commented:
changed the username to "domain\\user" but still no joy.
0
Todd GerbertIT ConsultantCommented:
Try opening the services control panel and changing it manually, tackle one problem at a time.

0
wint100Author Commented:
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
wint100Author Commented:
USed this articel to imperonsate the user running the code:

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

Works a treat. Thanks!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.