Windows service keeps on failing - c#

I have a windows service which is designed to continuously retrieve messages from Azure service bus queue and pass it to other queues.I have deployed this service to one of the server computer but unfortunately the service keeps failing at a random time interval.
My application handles the exceptions and writes them to a file.The main purpose of this application is to hook up to the queue and listen all the messages continuously and never move to the Application stop stage.I'm using a timer in this application and I don't think that is causing any problem.I'd like to know what would be the best approach to handle errors and make my application stable, below is the code. Thanks in advance.
public partial class Scheduler : ServiceBase
{
private Timer Scheduletimer = null;
private string servicenamespace;
private string issuesecretkey;
private string sourcequeue;
private string destinationqueue;
public Scheduler()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Scheduletimer = new Timer();
this.Scheduletimer.Interval = 1000;//1 sec
this.Scheduletimer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Tick);
Scheduletimer.Enabled = true;
WriteToFile("Application started : "+DateTime.Now.ToString());
}
protected void timer1_Tick(object sender, ElapsedEventArgs e)
{
Scheduletimer.Enabled = false;
WriteToFile("Business logic started : " + DateTime.Now.ToString());
//Business Logic code goes here
}
protected override void OnStop()
{
Scheduletimer.Enabled = false;
WriteToFile("Application stoped : "+DateTime.Now.ToString());
}
public void WriteToFile(string text)
{
string directory = AppDomain.CurrentDomain.BaseDirectory;
string logfilepath = directory + "LogFile.txt";
using (StreamWriter writer = new StreamWriter(logfilepath, true))
{
writer.WriteLine(text);
writer.Close();
}
}
public void WriteErrorsToFile(Exception ex)
{
string directory = AppDomain.CurrentDomain.BaseDirectory;
string Errorlogfilepath = directory + "ErrorLogFile.txt";
using (StreamWriter writer = new StreamWriter(Errorlogfilepath, true))
{
writer.WriteLine("Time Occured: " + DateTime.Now.ToString());
writer.WriteLine(ex.Message +" "+ DateTime.Now.ToString());
writer.Close();
}
}

Related

Why i can not start the windows service in thread?

I've code which starts depending whether the underlying application runs in console services instead of threads for the tasks. Here is a small cut of the main method:
//ANSAR BANK THREAD
Thread AnsarBankThread = new Thread(Ansar);
Console.WriteLine("Start The AnsarBankThread");
AnsarBankThread.Start();
//MELLAT BANK THREAD
Thread MellatBankThread = new Thread(Mellat);
Console.WriteLine("Start The MellatBankThread");
MellatBankThread.Start();
This is the code which will be executed:
static void Ansar()
{
var AnsarBank1 = new AnsarBank();
if (Environment.UserInteractive)
{
AnsarBank1.Start();
}
else
{
var servicesToRun = new ServiceBase[]{ AnsarBank1 };
ServiceBase.Run(servicesToRun);
}
}
static void Mellat()
{
var MellatBank1 = new MellatBank();
if (Environment.UserInteractive)
{
MellatBank1.Start();
}
else
{
var servicesToRun = new ServiceBase[]{ MellatBank1 };
ServiceBase.Run(servicesToRun);
}
}
and this is my AnsarBank service code:
protected override void OnStart(string[] args)
{
var timer = new System.Timers.Timer(5000); // fire every 30 second
timer.Elapsed += OnElapsedTime;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
File.WriteAllText(#"d:\Temp\Ansar.txt", "Ansar Bank Writer\n");
}
public void Start()
{
OnStart(new string[0]);
}
And this is my MellatBank Service:
protected override void OnStart(string[] args)
{
var timer = new System.Timers.Timer(5000); // fire every 30 second
timer.Elapsed += OnElapsedTime;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
File.WriteAllText(#"d:\Temp\MellatBank.txt", "Mellat Bank writer\n");
}
public void Start()
{
OnStart(new string[0]);
}
However, if I run the code there will be only the file Ansar.txt created and the file MellatBank.txt is missing!
Can someone encounter the problem in my code please? I would appreciate any help!
Chnage code to this:
System.Timers.Timer personalTimer = null;
public AnsarBank()
{
personalTimer = new System.Timers.Timer(5000);
InitializeComponent();
}
protected override void OnStart(string[] args)
{
//var timer = new System.Timers.Timer(5000); // fire every 30 second
personalTimer.Elapsed += OnElapsedTimeAnsar;
personalTimer.Enabled = true;
}
but so not work.
What's the problem?
1. Variable goes out of scope:
Thanks to #MatthewWatson: I also suggest moving the timer variable outside of the method right into the class. The timer object can be garbage collected directly because the garbage collector doesn't see that it's used any further.
Why thinks the gc that the variable isn't used anymore?
Simply because you created it in the method. It's local and because the class itself hasn't any reference to it there isn't any hint for the gc that it's needed further!
This should be true after I looked to this question.
Solution to this in sample code:
class SomeClass {
System.Timers.Timer personalTimer = null; //Timer is now garbage collected after the object of SomeClass goes out of scope!
SomeClass() {
personalTimer = new Syste.Timers.Timer(30000) // Now every 30 seconds!
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTime;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
}
....
}
2.File access problems
After I tried your code I encountered exceptions because the path may not exist. So I changed the code to create a path before the creation of a file. Also I added checks whether file exists and if so that text will be applied to the file. The old solution replaced the file everytime. This works for me fine. I don't know what you've done with InitializeComponents(...) this seems to be gui stuff, so I don't know.
Change your code in the service classes to following please:
namespace WebService
{
partial class MellatBank : ServiceBase
{
System.Timers.Timer personalTimer = null;
public MellatBank()
{
personalTimer = new System.Timers.Timer(1000);
this.ServiceName = "MellatBankService";
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTimeMellat;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
//var timer = new System.Timers.Timer(5000); // fire every 30 second
//personalTimer.Elapsed += OnElapsedTimeMellat;
//personalTimer.Enabled = true;
}
private void OnElapsedTimeMellat(object source, ElapsedEventArgs e)
{
try
{
if (!Directory.Exists(#"D:\Temp"))
Directory.CreateDirectory(#"D:\Temp\");
if (!File.Exists(#"D:\Temp\MellatBank.txt"))
{
var f = File.CreateText(#"D:\Temp\MellatBank.txt");
f.Write(#"D:\Temp\MellatBank.txt", "Mellat Bank writer\n");
f.Close();
}
else
{
var f = File.AppendText(#"D:\Temp\MellatBank.txt");
f.Write("Mellat Bank writer\n");
f.Close();
}
}
catch (System.Exception ex)
{
Console.Error.WriteLine("IO EXCEPTION: {0}", ex.ToString());
}
}
public void Start()
{
OnStart(new string[0]);
}
protected override void OnStop()
{
Console.Out.WriteLine("ended!");
// TODO: Add code here to perform any tear-down necessary to stop your service.
}
}
}
namespace WebService
{
partial class AnsarBank : ServiceBase
{
System.Timers.Timer personalTimer = null;
public AnsarBank()
{
personalTimer = new System.Timers.Timer(1000);
this.ServiceName = "AnsarBankService";
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTimeAnsar;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
//var timer = new System.Timers.Timer(5000); // fire every 30 second
//personalTimer.Elapsed += OnElapsedTimeAnsar;
//personalTimer.Enabled = true;
}
private void OnElapsedTimeAnsar(object source, ElapsedEventArgs e)
{
try
{
if (!Directory.Exists(#"D:\Temp"))
Directory.CreateDirectory(#"D:\Temp\");
if (!File.Exists(#"D:\Temp\Ansar.txt"))
{
var f = File.CreateText(#"D:\Temp\Ansar.txt");
f.Write(#"D:\Temp\Ansar.txt", "Ansar Bank writer\n");
f.Close();
}
else
{
var f = File.AppendText(#"D:\Temp\Ansar.txt");
f.Write("Ansar Bank Writer\n");
f.Close();
}
}
catch (System.Exception ex)
{
Console.Error.WriteLine("IO EXCEPTION: {0}", ex.ToString());
}
}
public void Start()
{
OnStart(new string[0]);
}
protected override void OnStop()
{
Console.Out.WriteLine("ended!");
}
}
}
Edit:
After viewing your code I saw that your services only run as long as your application runs. So your services may have been stopped before they could write anything which would explain your problem too.
PS:
Asker please practice the basics of Object Oriented Programming (OOP) again if you don't know what class fields are.

Windows service file listener only listens when debugging

First the code:
public partial class Watcher : ServiceBase
{
private const string PathToFolder = #"D:\print\";
public Watcher()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
private void fileWatcher_Changed(object sender, FileSystemEventArgs e)
{
if (e.Name != "test.txt")
{
return;
}
using (var r = new StreamReader(e.FullPath))
{
var json = r.ReadToEnd();
dynamic tempTest = JsonConvert.DeserializeObject(json);
const string filename = PathToFolder + "textParsed.txt";
if (File.Exists(filename))
{
File.Delete(filename);
}
using (var file = File.CreateText(filename))
{
file.WriteLine(tempTest.Name.ToString());
}
}
}
}
If there are changes to the text.txt file I'm suppose to parse the content of that text file and create another file. If I attach VS to the service and debug the service, the event gets fired, but when running normally, nothing happens.
The installer has LocalSystem privileges and that's pretty much all the changes I've made... Should be pretty straight forward, but somehow isn't.

Using CacheItemRemovedCallback to simulate a Windows Service acts different on first run

I simulated a Windows Service with the CacheItemRemovedCallback, based on this source:
Simulate a Windows Service using ASP.NET to run scheduled jobs
Everything is working great, except from the first run after the application recycles or restart.
Global.asax.cs
protected void Application_Start(object sender, EventArgs e)
{
RegisterCacheEntry();
}
private bool RegisterCacheEntry()
{
if (null != HttpContext.Current.Cache[DummyCacheItemKey]) return false;
int interval = Properties.Settings.Default.SchedulerInterval;
HttpContext.Current.Cache.Add(
DummyCacheItemKey, "StartingScheduler", null,
Cache.NoAbsoluteExpiration, TimeSpan.FromHours(interval),
CacheItemPriority.NotRemovable,
new CacheItemRemovedCallback(CacheItemRemovedCallback)
);
return true;
}
public void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason)
{
Scheduler.HitPage(Properties.Settings.Default.Dummy);
string dirScheduler = Properties.Settings.Default.Scheduler;
Scheduler.Manage(dirScheduler);
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.Url.ToString() == Properties.Settings.Default.Dummy)
{
RegisterCacheEntry();
}
}
public static class Scheduler
public static string _DirScheduler { get; set; }
public static void Manage(string dirScheduler)
{
_DirScheduler = dirScheduler;
string[] schedulesCfg = Directory.GetFiles(dirScheduler, "*.xml");
foreach (string scheduleCfg in schedulesCfg)
{
//scheduleData = Class to store the schedule data
ThreadPool.QueueUserWorkItem(o => FireAway(scheduleData));
}
}
private static void FireAway(Schedule schedule)
{
string month = DateTime.Now.Month.ToString();
if (month.Length == 1)
{
month = month.Insert(0, "0");
}
// Wait Handle to Manage Access to Log File
EventWaitHandle waitHandle = new EventWaitHandle(true, EventResetMode.AutoReset, "LogFile_Shared");
// Lock the log file
waitHandle.WaitOne();
WriteLog("path_to_log_file", schedule, "started");
// Release the lock on log file
waitHandle.Set();
// Ok until here !
string message = ScheduleScript.Launch(schedule);
// Code not executed from here (only after application end or recycle)
if (schedule.Repeat == "0")
{
waitHandle.WaitOne();
UpdateScheduler(schedule);
waitHandle.Set();
}
// Lock the log file
waitHandle.WaitOne();
WriteLog("path_to_log_file", schedule, message);
// Release the lock on log file
waitHandle.Set();
}
private static void UpdateScheduler(Schedule schedule)
{
// Update a xml file containing scheduler data
}
public static class ScheduleScript
public static string Launch(Schedule schedule)
{
string message = "finished";
string messageScheduler = string.Empty;
using (WebClientCustom web = new WebClientCustom(10800000)) // 3 hours timeout
{
try
{
string res = web.DownloadString(schedule.Script);
}
catch (Exception e)
{
message = e.Message;
}
}
return message;
}
In the static class Scheduler, everything is executed until ScheduleScript.Launch(schedule). Then, the code is not executed (the log is not updated with Status finished and the Scheduler xml is not updated either with the UpdateScheduler method).
I tried everything I could without success. This situation happened only when a schedule starts after the application is recycled.
This behavior happen for example if I have a schedule expected to launch at 10am and has not yet been executed and I publish a new version of the application or manually execute an application pool recycle in the same hour (10am) of the schedule.

Windows service sometimes won't start (eratic behaviour)

At the moment I'm developing a series of Windows services in C#, that use a timer (from System.Timers) to poll the machine they are running on and report stats to a remote listener (remote machine hosts a WCF data service).
The setup is as follows: I have a class that wraps System.Timers.Timer with additional functionality, accepting a generic event handler to be fired when the timer elapses and log information:
public class GenericPoller
{
private EventLog _log;
private string _componentName;
private System.Timers.Timer _timer;
public GenericPoller
(
double interval,
System.Timers.ElapsedEventHandler handler,
EventLog log,
string componentName
)
{
_componentName = componentName;
_log = log;
_timer = new System.Timers.Timer();
_timer.Interval = interval;
_timer.AutoReset = true;
_timer.Enabled = false;
_timer.Elapsed += handler;
}
public void StartPolling()
{
try
{
_timer.Enabled = true;
_log.WriteEntry
(
"Timer started for component '" + _componentName
+ "', with " + _timer.Interval + "ms interval."
);
}
catch
{
_log.WriteEntry("Failed to start timer for component '" + _componentName + "'.");
}
}
public void StopPolling()
{
try
{
_timer.Enabled = false;
_log.WriteEntry("Timer stopped for component '" + _componentName + "'.");
}
catch
{
_log.WriteEntry("Failed to stop timer for component '" + _componentName + "'.");
}
}
}
Any one of the services I'm implementing creates a GenericPoller in their constructor, and in the OnStart method I invoke StartPolling via a separate thread to consume as little time as possible inside this method. The service class looks roughly like this:
public partial class CPUMonitor : ServiceBase
{
private GenericPoller _poller;
Thread _thread;
public CPUMonitor()
{
InitializeComponent();
_poller = new GenericPoller
(
HardwareMonitorCommon.Instance.DefaultPollingInterval,
PollCPU,
EventLog,
"CPUMonitor"
);
}
protected override void OnStart(string[] args)
{
_thread = new Thread(new ThreadStart(_poller.StartPolling));
_thread.Start();
}
protected override void OnStop()
{
_poller.StopPolling();
_thread.Join();
}
private void PollCPU(object sender, System.Timers.ElapsedEventArgs e)
{
Code to aqcuire CPU stats and report to WCF data service...
}
}
I install the services with the installutil.exe command.
The services will sometimes fail to start within the allotted time (error 1053), but there doesn't seem to be any pattern to this problem. Failure to start is about 4 attempts out of 10.
I simply can't understand why this happens. The System/Application event log doesn't report any errors or exceptions from the service processes, and I can't figure out why a timeout would occur if all the "heavy lifting" is taking place in a separate thread.
I'm in no way a pro/expert at writing multithreaded code, so I fully expect to be doing something wrong...I just can't see what it is...
EDIT: the Main method remains in the automatically generated Program.cs file, and I only modified it to add the components that will be run:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new CPUMonitor(),
new MemoryMonitor()
};
ServiceBase.Run(ServicesToRun);
}
}

C# Windows service not starting

I try to create a windows service which automatically startsup.
I am able to install and deinstall the service. If I try to start it, I get following error message: "Der Dienst antwortete nicht rechtzeitig auf die Start- oder Steueranfrage". (I try to translate) "The service don't respont in time on start or control request".
Here is my poor code
public class LisaServerService: System.ServiceProcess.ServiceBase
{
private Program lisaServerServiceProgram;
public static string LisaServiceName = "LISA-ServerService";
[STAThread]
public static void Main(string[] args)
{
LisaServerService lisaServerService = new LisaServerService();
if (Environment.UserInteractive)
{
lisaServerService.OnStart(args);
Console.WriteLine("I am a service. Normally you can't see the console... just ignore me");
Console.ReadLine();
lisaServerService.OnStop();
}
else
{
ServiceBase.Run(lisaServerService);
}
}
public LisaServerService()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.CanShutdown = true;
this.ServiceName = "LISA - ServerService";
this.CanPauseAndContinue = true;
this.lisaServerServiceProgram = new Program();
}
protected override void OnStart(string[] args)
{
lisaServerServiceProgram.Start(null);
base.OnStart(args);
}
protected override void OnStop()
{
lisaServerServiceProgram.Stop();
base.OnStop();
}
protected override void OnShutdown()
{
OnStop();
base.OnShutdown();
}
}
Program.cs
public class Program
{
public Program()
{
Logger.LogLevel = LogLevel.Information;
Logger.LogRange = LogRange.Write;
Logger.Log("Logger initialized");
}
public void Start(string[] args)
{
DatabaseHandler.StartDatabase();
NetworkHandler.StartNetwork();
Logger.Log("Service started");
}
if I run the service as a console program, it works fine.
So the db connection + logger are working fine too. (Also within < 10ms)
If you're running the service in interactive mode it's waiting for the console here:
if (Environment.UserInteractive)
{
lisaServerService.OnStart(args);
Console.WriteLine("I am a service. Normally you can't see the console... just ignore me");
Console.ReadLine();
...
That is likely preventing the service from responding properly to indicate it is started.

Categories