-1

I have a console application that silently prints webPage. Ref: Print WebBrowser without previewing i.e. single click print

I am trying to convert it to a Windows Service. Code works fine in Debug Mode but fails in the Release mode (after I install the service). Event Viewer has error as :

Faulting application name: TestWindowsService.exe, version: 1.0.0.0, time stamp: 0x59c94fa7
Faulting module name: MSHTML.dll, version: 11.0.9600.18792, time stamp: 0x59908408

This is the full code ( I took printing google.com as an example) :

using System;
using System.ServiceProcess;
using System.Timers;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace TestWindowsService
{
    public partial class Scheduler : ServiceBase
    {
        private System.Timers.Timer timer1 = null;
        public Scheduler()
        {
            InitializeComponent();
        }

        public void onDebug()
        {
            OnStart(null);
        }

        protected override void OnStart(string[] args)
        {

            timer1 = new System.Timers.Timer();
            this.timer1.Interval = 3000; //every 3 seconds
            this.timer1.Elapsed += new ElapsedEventHandler(this.timer1_Tick);
            timer1.AutoReset = false;
            timer1.Enabled = true;
        }

        private void timer1_Tick(object sender, ElapsedEventArgs e)
        {
            try
            {

                var task = MessageLoopWorker.Run(DoWorkAsync, "http://www.google.com");
                task.Wait();
                Console.WriteLine("DoWorkAsync completed.");

            }
            catch (Exception ex)
            {
                Console.WriteLine("DoWorkAsync failed: " + ex.Message);
            }
            finally
            {
                if (null != timer1)
                {
                    timer1.Start();
                }
            }
        }

        public static class MessageLoopWorker
        {
            public static async Task<object> Run(Func<object[], Task<object>> worker, params object[] args)
            {
                var tcs = new TaskCompletionSource<object>();

                var thread = new Thread(() =>
                {
                    EventHandler idleHandler = null;

                    idleHandler = async (s, e) =>
                    {
                        // handle Application.Idle just once
                        Application.Idle -= idleHandler;

                        // return to the message loop
                        await Task.Yield();

                        // and continue asynchronously
                        // propogate the result or exception
                        try
                        {
                            var result = await worker(args);
                            tcs.SetResult(result);
                        }
                        catch (Exception ex)
                        {
                            tcs.SetException(ex);
                        }

                        // signal to exit the message loop
                        // Application.Run will exit at this point
                        Application.ExitThread();
                    };

                    // handle Application.Idle just once
                    // to make sure we're inside the message loop
                    // and SynchronizationContext has been correctly installed
                    Application.Idle += idleHandler;
                    Application.Run();
                });

                // set STA model for the new thread
                thread.SetApartmentState(ApartmentState.STA);

                // start the thread and await for the task
                thread.Start();
                try
                {
                    return await tcs.Task;
                }
                finally
                {
                    thread.Join();
                }
            }
        }

        // navigate WebBrowser to the list of urls in a loop
        static async Task<object> DoWorkAsync(object[] args)
        {
            //logger.Info("Start working.");
            var wb = new WebBrowser();
            wb.ScriptErrorsSuppressed = true;

            if (wb.Document == null && wb.ActiveXInstance == null)
            {
                //logger.Info($"Unable to initialize the underlying WebBrowserActiveX");
                throw new ApplicationException("Unable to initialize the underlying WebBrowserActiveX");
            }
            // get the underlying WebBrowser ActiveX object;
            var wbax = (SHDocVw.WebBrowser)wb.ActiveXInstance;
            TaskCompletionSource<bool> loadedTcs = null;
            WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (s, e) =>
                loadedTcs.TrySetResult(true); // turn event into awaitable task

            TaskCompletionSource<bool> printedTcs = null;
            SHDocVw.DWebBrowserEvents2_PrintTemplateTeardownEventHandler printTemplateTeardownHandler = (p) =>
                printedTcs.TrySetResult(true); // turn event into awaitable task

            // navigate to each URL in the list
            foreach (var url in args)
            {
                loadedTcs = new TaskCompletionSource<bool>();
                wb.DocumentCompleted += documentCompletedHandler;
                try
                {
                    wb.Navigate(url.ToString());
                    // await for DocumentCompleted
                    await loadedTcs.Task;
                }
                finally
                {
                    wb.DocumentCompleted -= documentCompletedHandler;
                }

                // the DOM is ready, 
                //Console.WriteLine(url.ToString());
                //Console.WriteLine(wb.Document.Body.OuterHtml);

                // print the document
                printedTcs = new TaskCompletionSource<bool>();
                wbax.PrintTemplateTeardown += printTemplateTeardownHandler;
                try
                {
                    wb.Print();
                    // await for PrintTemplateTeardown - the end of printing
                    await printedTcs.Task;
                }
                finally
                {
                    wbax.PrintTemplateTeardown -= printTemplateTeardownHandler;
                }
                //logger.Info($"{url.ToString()}  is Complete ");
                //Console.WriteLine(url.ToString() + " printed.");
            }

            wb.Dispose();
            return null;
        }

        protected override void OnStop()
        {
        }
    }
}

This is Program.cs

using System;
using System.ServiceProcess;
using System.Text;
using System.Threading;

namespace TestWindowsService
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {

#if DEBUG
            Scheduler myservice = new Scheduler();
            myservice.onDebug();
            Thread.Sleep(Timeout.Infinite);

#else
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Scheduler()
            };
            ServiceBase.Run(ServicesToRun);
#endif
        }
    }
}

What am I doing wrong? Any pointers?

ProgSky
  • 2,530
  • 8
  • 39
  • 65

2 Answers2

1

maybe you need to :

  1. Set service LogOn as "Local System account".

  2. Select "Allow Service to interact with desktop".

enter image description here

yaniv
  • 913
  • 8
  • 16
  • Thanks for your response yaniv. I tried this option, but it doesn't work. Looks like this option has been disabled since VISTA. Have a look at this discussion. https://stackoverflow.com/questions/4237225/allow-service-to-interact-with-desktop-in-windows – ProgSky Sep 25 '17 at 19:42
1

My Issue was Session 0 isolation feature added in VISTA and Subsequent OS Releases.

I solved my issue with the help of these link:

C# Windows Service Creates Process but doesn't executes it

Printing from a Windows Service

https://social.msdn.microsoft.com/Forums/vstudio/en-US/75e06571-cb7d-4c77-bdbc-4983fd8cfad6/print-pdf-from-windows-service?forum=csharpgeneral

ProgSky
  • 2,530
  • 8
  • 39
  • 65