I have an application that schedules jobs using Quartz.Net. It works on my development laptop perfectly both as a winforms application (with start and stop buttons) and as a Windows Services whose OnStart() and OnStop() event code matches the start and stop button code of the winforms application. They're both in the same solution using the same "model" code (in its own project).
If I run the winforms application on the production computer it works perfectly, the jobs are executed according to their schedule as expected. However if I install and run it as a Windows Service on the production PC nothing happens! The jobs do not run.
I have no idea how to debug this. Please let me know if you have any suggestions as to what might be wrong.
Also please let me know what other information I should be providing.
Oh - dev PC is running Windows 7, production PC is running Windows 8.1! Could that be the problem? I built the service by following this tutorial: http://msdn.microsoft.com/en-us/library/zt39148a(v=vs.110).aspx which does not indicate that anything special needs to be done for deploying to Windows 8?
Could this have something to do with environment variables (which I know nothing about)?
Here is some code which may be relevant:
The service:
namespace DataPump
{
public partial class DataPumpService : ServiceBase
{
private TaskManager _taskManager;
public DataPumpService()
{
InitializeComponent();
_taskManager = new TaskManager();
}
protected override void OnStart(string[] args)
{
_taskManager.Go();
}
protected override void OnStop()
{
_taskManager.Stop();
}
}
}
The form code (different project):
namespace DataPump
{
public partial class Form1 : Form
{
private TaskManager _taskManager = new TaskManager();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
_taskManager.Go(); //Loops infinitely, does not block
label1.Text = "Running...";
}
private void button2_Click(object sender, EventArgs e)
{
label1.Text = "Stopping...";
_taskManager.Stop();
label1.Text = "Idle";
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_taskManager.Stop();
}
}
}
Selected code from TaskManager code (third project which the first two each reference):
public class TaskManager
{
//...
private IScheduler _scheduler = StdSchedulerFactory.GetDefaultScheduler();
//...
public void Go()
{
if (_scheduler.GetCurrentlyExecutingJobs().Count() == 0)
{
_scheduler.Start();
_scheduler.AddCalendar(CalendarName, MakeSAPublicHolidayCalendar(), false, true);
foreach (DatapumpJob job in JobList)
{
_scheduler.ScheduleJob(MakeJob(job), MakeTriggerCron(job));
}
}
}
//...
public void Stop()
{
foreach (string name in _scheduler.GetCurrentlyExecutingJobs().Select(j => j.JobDetail.Key.Name))
{
_scheduler.Interrupt(new JobKey(name));
}
_scheduler.Shutdown(true);
}
//...
}
Where JobList is a get only property that generates a List<DatapumpJob>where DatapumpJob implements IInterrutableJob but adds common features including a job name which gets use by the three methods beginning Make... which are all private methods within the TaskManager class.
This code is to answer a question from the comments regarding ServiceBase.Run():
Program.cs (auto-generated):
namespace DataPump
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new DataPumpService()
};
ServiceBase.Run(ServicesToRun);
}
}
}
This turned out to be a network permissions issue. The service was running, it was just unable to access the network drive. So really my question was mi-specified.
After trying this: https://serverfault.com/questions/177139/windows-service-cant-access-network-share we eventually got it to work by setting the service to run as a specific user account on the PC.
Related
The windows service i coded is not working:
Intended funcionality: The service is supposed to receive messages from Windows Message Queue (MSMQ) and write the messages on .txt files.
It works when I run it not-as-a-service (directly from visual studio)
When I installed it as a service i can start it, but it doesn't do anything, not creating/writing .txt files anywhere
(I know it isn't writing the files elsewhere because when I run the program from VS the messages are still in the queue, so they weren't taken out by the service)
The difference between running it as a service and running it from visual studio is the next:
namespace ComponentAtrapador
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
#if DEBUG
Service1 myService = new Service1();
myService.startMethod();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
#endif
}
}
}
(so if i run it as DEBUG it will run without me having to install it as a service)
Here's the service's code:
namespace ComponentAtrapador
{
public partial class Service1 : ServiceBase
{
private System.Timers.Timer _timer;
private System.ComponentModel.IContainer components1;
private System.Diagnostics.EventLog eventLog1;
public void startMethod()
{
OnStart(null);
}
public Service1()
{
InitializeComponent();
eventLog1 = new System.Diagnostics.EventLog();
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
_timer = new System.Timers.Timer();
_timer.Interval = 5000; // 5 seconds
_timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
_timer.Start();
}
protected override void OnStop()
{
_timer.Stop();
}
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
string nombreArchivo = "archivoMensaje";
MessageQueue messageQueue = new MessageQueue(#".\Private$\SomeTestName");
System.Messaging.Message[] messages = messageQueue.GetAllMessages();
System.Messaging.Message m = new System.Messaging.Message();
foreach (System.Messaging.Message message in messages)
{
message.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
string text = message.Body.ToString();
System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + nombreArchivo + Properties.Settings.Default.SettingNumero + ".txt", text);
Properties.Settings.Default.SettingNumero++;
Properties.Settings.Default.Save();
//Do something with the message.
}
// after all processing, delete all the messages
messageQueue.Purge();
//}
}
}
}
That is where Logs are so helpful, put couple of eventLog1.WriteEntry() inside your OnTimer method and you will see where is it failing.
I would check
how many messages I am getting.
I will put one eventLog1.WriteEntry() inside loop to see what is happening with each message etc...
Turns out the service didn't have enough permissions, fixed it by setting the serviceProcessInstaller of the service on visual studio to User, so that when i installed it it'd ask for credentials. Just had to type "./[username]" when it asked for my username for it to work.
Another way of fixing it would be going into the task manager > services > right click service > properties > security. And change the permissions there.
I am learning basics of windows service. I have created a very simple one.
using System.ServiceProcess;
namespace WindowsServiceBasic
{
public partial class OmerService : ServiceBase
{
public OmerService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
System.Diagnostics.Debugger.Launch();
WriteLog("START");
}
protected override void OnStop()
{
System.Diagnostics.Debugger.Launch();
WriteLog("STOP");
}
private void WriteLog(string durum)
{
eventLog1.WriteEntry(performanceCounter1.RawValue.ToString());
}
}
}
using System;
using System.IO;
using System.ServiceProcess;
namespace WindowsServiceBasic
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
private static void Main()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new OmerService()
};
ServiceBase.Run(ServicesToRun);
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e != null && e.ExceptionObject != null)
{
string createText = e.ToString();
File.WriteAllText(#"c:\omerlog.txt", createText);
}
}
}
}
The first time my service (AServis) starts successfully but when I click the restart it crashes. Since my service is very simple It should have been worked properly. I try to log the error, put try catch but I could not find anything. I am trying to attach process, it debugs stop event but after stop debug suddenly finishes and start process crashes. Could you please help me what is the reason and how can I debug and log error.
Thanks in advance
I saw that it was stuck in
public OmerService()
{
InitializeComponent();
}
I could see the issue adding System.Diagnostics.Debugger.Launch(); statement.
public OmerService()
{
System.Diagnostics.Debugger.Launch();
InitializeComponent();
}
The standard trick I use in this situation is to add a call to System.Diagnostics.Debugger.Break in my start up code. Now, when you start the service as normal (through the Service Control Manager (SCM)), the call to the Break will cause Windows to launch the JIT debugger, which should prompt you to choose the debugger you wish to attach to the process (e.g., Visual Studio), which will then enable you to debug your code as normal.
Also see this: Easier way to debug a Windows service.
I tried to deploy one service which works great in local to the production server. But on this server, the ElapsedEventHandler seems to never call my method Tick()
I have read other similar threads as
First Windows Service - timer seems not to tick
or
Timer tick event is not called in windows service
but i couldn't have any answer to my problem :/
I also tried to use _timer.Enabled=1 instead of _timer.Start (no incidence normally but still tried) and also tried to reinstall service a couple of times.
I use the Timer from Class System.Timers.
here is my code :
static void Main()
{
var servicesToRun = new ServiceBase[]
{
new SynchronizeEvents()
};
#if DEBUG
servicesToRun.LoadServices();
#else
ServiceBase.Run(servicesToRun);
#endif
}
and
public partial class SynchronizeEvents : ServiceBase
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();//Nlog
private Timer _timer;//From Class System.Timers
private readonly DbSetName _db = new DbSetName ();
private static readonly Dictionary<Employee, otherStuff> Subscriptions = new Dictionary<Employee, otherStuff>();
public SynchronizeEvents()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_logger.Trace("Service Start");
_timer = new Timer(5000) { AutoReset = false };//Same problem without AutoReset = false
_timer.Elapsed += Tick;
_timer.Start();
_logger.Trace("End OnStart");
}
protected override void OnShutdown()
{
_logger.Trace("OnShutdown");
_timer.Stop();
base.OnShutdown();
}
protected void Tick(object sender, ElapsedEventArgs elapsedEventArgs)
{
_logger.Trace("Tick");
_timer.Stop();
Compute();
_timer.Start();
}
protected override void OnStop()
{
_logger.Trace("OnStop");
}
Everything works great while on DebugMode and also on local computer in Release mode, but when i install it on production server the only logs i got are :
2014-09-08 16:35:57.1929 TRACE Service Start
2014-09-08 16:35:57.2085 TRACE End OnStart
i also got this when i stop the service...
2014-09-08 16:40:52.4072 TRACE End OnStop
Actually i got to apologize to Steve Wellens, he was right to ask about what Compute do.
The problem was related to Compute().
It had some code which required a DLL which was missing.
I don't know why _logger.Trace("Tick"); wasn't called and no Exception was triggered :/
I had to comment my program line per line to find out where the problem came from...
I created a C# windows service and installed it successfully on my local developer machine (it works well).
Now I'm trying to install the service on a different machine.
I copied the "Release" folder to the new machine and installed the service.
When I start the service on the new machine I get the following error:
"service on Local Computer started and then stopped. Some services stop automatically if they are not in use by other services or programs."
I don't get any message to the Application event log, I even added debug message as the first line of the program, but i see nothing in the Event Viewer (as if the code doesn't start at all). :/
What have i done wrong?
"started and then stopped" message usually appears when your server throws an exception during start up. Which could be for many reasons, including invalid paths and inability to write to the Application Event Log due to missing source or insufficient privileges.
I usually include an option to run my service as a console app.
Which allows me to display any exceptions using Console.WriteLine.
Following assumes your service extends from System.ServiceProcess.ServiceBase.
partial class MyService : ServiceBase
{
private static void Main(string[] args)
{
MyService svc = new MyService();
if (Environment.UserInteractive)
RunConsole(args, svc);
else
Run(svc);
}
public MyService()
{
InitializeComponent();
}
protected static bool KeepRunning { get; set; }
protected override void OnStart(string[] args)
{
StartServiceHost();
}
protected override void OnStop()
{
StopServiceHost();
}
protected override void OnShutdown()
{
StopServiceHost();
base.OnShutdown();
}
private static void RunConsole(string[] args, ConverterService svc)
{
// need to hold on to Ctrl+C, otherwise StopServiceHost() never gets called
Console.CancelKeyPress += (sender, e) => ShutDown(svc);
KeepRunning = true;
svc.OnStart(args);
Console.WriteLine("Press <Ctrl+C> to exit.");
while (KeepRunning)
{
Console.ReadLine();
}
}
private void StartServiceHost()
{
// start your service
}
private void StopServiceHost()
{
// stop your service
}
private static void ShutDown(MyService svc)
{
Console.WriteLine("exiting...");
svc.OnStop();
KeepRunning = false;
}
}
Well, I've found the problem:
I used password decryption with DataProctionScope.LocalMachine.
So when I changed the machine- the decryption failed.
I had to re-encrypt the passwords on the local machine and then the decryption worked fine.
Thank you for your responds!
*The eventlog debugging didn't work because of my fault.
I've googled this one
but when i'm trying to apply it i get an error. So install/uninstall works fine, but service itself just doesn't start and after timeout it says that service doesn't respond. I don't know why. When i'm attaching to process it even doesn't enter into Main() method, static constructors and so on. I've used this addon for attach.
public static void Main()
{
AppDomain.CurrentDomain.UnhandledException += OnException;
if (Environment.UserInteractive)
{
AskUserForInstall();
}
else
{
ServiceBase.Run(new NotificatorService());
}
}
Service is also very simple:
using System.ServiceProcess;
using System.Windows;
namespace AZNotificator
{
public partial class NotificatorService : ServiceBase
{
static NotificatorService()
{
int x = 5;
}
public NotificatorService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
MessageBox.Show("Hello");
}
protected override void OnStop()
{
}
}
}
You can not call MessageBox.Show("Hello"); from the windows service since the service does not have the GUI.
If you want to do some interaction from the windows service have a look at this article
http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx
So remove MessageBox.Show("Hello"); from your OnStart method and your service should start just fine.