2017-09-25 5 views
-2

J'ai une application console qui imprime silencieusement webPage. Ref: Print WebBrowser without previewing i.e. single click printC# Service Windows - Le contrôle WebBrowser ne fonctionne pas en mode édition

Je suis en train de le convertir en un service Windows. Le code fonctionne correctement en mode débogage mais échoue en mode de libération (après avoir installé le service). Observateur d'événements a erreur:

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 

Ceci est le code complet (j'ai pris impression google.com par exemple):

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() 
     { 
     } 
    } 
} 

C'est 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 
     } 
    } 
} 

Qu'est-ce que est-ce que je fais mal? Des pointeurs?

+0

Je ne sais pas pourquoi cela fonctionnerait dans Debug et ne parviennent dans la version. – ProgSky

Répondre

1

vous devez peut-être:

  1. Set LogOn de service en tant que "compte système local".

  2. Sélectionnez "Autoriser le service à interagir avec le bureau".

enter image description here

+0

Merci pour votre réponse yaniv. J'ai essayé cette option, mais cela ne fonctionne pas. On dirait que cette option a été désactivée depuis VISTA. Jetez un oeil à cette discussion. https://stackoverflow.com/questions/4237225/allow-service-to-interact-with-desktop-in-windows – ProgSky