I have a .NET Console application using TopShelf to run this app as a windows service. The Console application itself has no problem running and doing what it is supposed to do. I have TopShelf nuget package installed and have configured the TopShelf correctly (to my knowledge).
When I debug the application or even after I installed the application into Windows service and started the service, it does not seem to execute the method "DoUpdate" I have defined the timer to be executed in the elapsed event. But it is not happening. Any clue anyone?
Here is my Main method in the Console Application:
public static void Main()
{
try
{
HostFactory.Run(x =>
{
x.Service<DNSUpdateTopShelf>(a =>
{
a.ConstructUsing(n => new DNSUpdateTopShelf());
a.WhenStarted(ts => ts.Start());
a.WhenStopped(ts => ts.Stop());
});
x.SetDescription("Update GoDaddy DNS Records");
x.SetDisplayName("GoDaddy DNS Updater");
x.SetServiceName("GoDaddyDNSUpdate");
//x.RunAsNetworkService();
x.RunAsLocalSystem();
x.StartAutomatically();
});
}
catch (Exception e)
{
System.Console.WriteLine(e.Message);
}
System.Console.WriteLine("---------------");
System.Console.ReadKey();
}
Here is the Class that does the work:
public class DNSUpdateTopShelf
{
private System.Timers.Timer updateTimer;
private int interval;
private EventLog log;
public DNSUpdateTopShelf()
{
Initialize();
}
public void Initialize()
{
//log = new EventLog("DynaProLogs");
updateTimer = new System.Timers.Timer();
}
public void Start()
{
try
{
Utils.WriteLog("In Start Method");
var jsonFile = $"{Directory.GetCurrentDirectory()}\\appconfig.json";
using (StreamReader r = new StreamReader(jsonFile))
{
var json = r.ReadToEndAsync().Result;
var config = (JObject)JsonConvert.DeserializeObject(json);
interval = config["interval"].Value<int>();
}
updateTimer.Interval = interval;
updateTimer.Elapsed += new ElapsedEventHandler(DoUpdate);
}
catch (Exception ex)
{
Utils.WriteLog($"DNSUpdater - {ex.Message}", type: EventLogEntryType.Error);
throw;
}
}
public void Stop()
{
Utils.WriteLog("In Stop Method");
updateTimer.Stop();
}
public void DoUpdate(object sender, ElapsedEventArgs e)
{
Utils.WriteLog("In DoUpdate method");
DNSUpdater updater = new DNSUpdater();
var results = Task.Run( async () => await updater.UpdateAllDomainIPAsync()).Result;
//var results = updater.UpdateAllDomainIPAsync().Result;
foreach (UpdateResult result in results)
{
Utils.WriteLog($"{result.RequestURI} -- {result.Message}");
}
}
}
The problem is: The DoWork method does not get called ever. I have changed the ElapsedTime of the timer to many different duration. But it never seems to get called at all.
I can confirm that the "Interval" property of the timer object does get set. I can also confirm that this service gets installed in Windows Service and is running. As I said, I tried to test it both by debugging the whole application including TopShelf as well as after building and installing it as a service. I can't figure out why the timer elapsed event handler (DoUpdate) is not firing.
After a painstaking googling for an answer, I finally got it. In case someone else has the same problem, here is what I did. I was missing couple of settings on the timer object. In my Start() method, I had set the AutoReset and Enabled properties of the timer object. With this modification, it now fires the ElapsedTime event and the application works as expected.
Here is my modified code:
updateTimer.Elapsed += new ElapsedEventHandler(DoUpdate);
updateTimer.AutoReset = true;
updateTimer.Enabled = true;