[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

Print Report to Printer c#.

Posted on 2009-07-06
15
Medium Priority
?
4,223 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
15 Comments
 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 2000 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 2000 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
Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…

650 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