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?
Je ne sais pas pourquoi cela fonctionnerait dans Debug et ne parviennent dans la version. – ProgSky