Windows Service Start and Stop C# - c#

I have developed a windows service to get fingerprint attendance data from a fingerprint machine time to time by using a thread and insert into ms SQL database. When I run the service in my local computer it's working fine but when I install and run it in server 2012 the service start and then stop.Please help me out.
protected override void OnStart(string[] args)
{
new LogManagement().WriteToLog("Service Started -" + DateTime.Now);
new LogManagement().WriteToLog("Thread Started" + DateTime.Now);
RunThread();
}
protected override void OnStop()
{
new LogManagement().WriteToLog("Service Stopped -" + DateTime.Now);
}
public void RunThread()
{
Thread thread = new Thread(new ThreadStart(DeviceChecker));
thread.IsBackground = true;
thread.Name = "DeviceCheckingThread";
thread.Start();
}
private void DeviceChecker()
{
//Process reading data and insert into database
Thread.Sleep(10000);
}

Have a look at this walkthrough.
I think you need to call SetServiceStatus method (from advapi32.dll) inside your OnStart method, or Service Control Manager will shut your service down, if it takes to long for startup.

Related

C#: Windows Console Application to Windows Service

I have a console application that tracks the performance of the computer, and I am trying to make it into a Windows Service. The service installs fine, however when I go into task manager and try to run the service I get Error 1053: the service did not respond to the start or control request in a timely fashion. In the task manager the service sometimes has a "starting" status, but it will not run.
On top of that, when I run the console app, I also get an error stating that: Cannot start service from the command line or a debugger. A windows service must first be installed - which I have done.
This is my program class:
public static string ServiceName = "performanceService";
static void Main(string[] args)
{
if (!Environment.UserInteractive)
{
PerformanceCounter ramCount = new PerformanceCounter("Memory", "Available MBytes");
PerformanceCounter cpuCount = new PerformanceCounter("Processor", "% Processor Time", "_Total");
Console.WriteLine("Press any key to view other information...\n");
Console.WriteLine("CPU and RAM information");
while (!Console.KeyAvailable)
{
double perf = cpuCount.NextValue();
Console.WriteLine("CPU Performance: " + perf + " %");
... Code continues on that calculates the performance and displays it in the console...
}
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new ServiceControl()
};
ServiceBase.Run(ServicesToRun);
}
}
This is my ServiceControl class:
public ServiceControl()
{
ServiceName = Program.ServiceName;
InitializeComponent();
}
public void Start()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
}
protected override void OnStop()
{
base.OnStop();
}
private void InitializeComponent()
{
//
// ServiceControl
//
this.ServiceName = "performanceService";
}
To install the service I have used both the Project Installer and manual install, just out of curiosity to be honest.
I changed the time limit through regedit, and that did not help.
Please let me know if you need to see additional code.
My question is, am I missing something from the code, that will not allow my service to start?
Thanks for your help.
Thank you for all your help.
The problem was that I had the Start() method in the ServiceControl class and I had my code the other way around in the Program class.
I was supposed to have the code to start the service in the if statement and the performance logic in the else, so that the start method executes quickly, like one of the comments suggested. After clicking start on the service in the task manager, the status changes to "running".
Thank you again.

Windows Service stuck on "starting" status as local system account

I developed a http server via console application in C# and decided to turn it into a Windows service to be able to initialize it without the need to login the machine.
I followed all the steps in How to create Windows Service and chose the account as "Local System", but when I install in my server machine and push the start button it takes a while and gives the following error:
Erro 1053: The service did not respond to the start or control request in timely fashion.
After that, the service status stays stuck in "starting" and the application don't work and I can't even stop the service anymore.
Trying to work around this problem, I changed it to "Network Service", so it started normally, but the application was not listening in the port I set when I checked in the prompt with the command "netstat -an". But the application listens normally if i run it as a console application.
So I am looking for an answer to one of these two questions:
What should I do to make the service starts properly with a Local System account?
If I decide to use Network service account, what should I care about to guarantee that my service works properly as a server?
When I converted my console application to windows service I simply put my code directly in the OnStart method. However, I realized the OnStart method should start the service, but needs to end some time to the service indeed start. So I created a thread that runs my service and let the OnStart method finish. I tested and the service worked just fine. Here is how it was the code:
protected override void OnStart(string[] args)
{
Listener(); // this method never returns
}
Here is how it worked:
protected override void OnStart(string[] args)
{
Thread t = new Thread(new ThreadStart(Listener));
t.Start();
}
But I still don't understand why the service ran (passed the "starting" status, but didn't work) when I used network service account. If anyone knows, I'll be glad to know the reason.
If you have a service that is not responding or showing pending in Windows services that you are unable to stop, use the following directions to force the service to stop.
Start -> Run or Start -> type services.msc and press Enter
Look for the service and check the Properties and identify its service name
Once found, open a command prompt. Type sc queryex [servicename]
Identify the PID (process ID)
In the same command prompt type taskkill /pid [pid number] /f
Find PID of Service
sc queryex <SERVICE_NAME>
Give result's below
SERVICE_NAME: Foo.Services.Bar TYPE : 10 WIN32_OWN_PROCESS STATE : 2 0 START_PENDING (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN) WIN32_EXIT_CODE : 0 (0x0) SERVICE_EXIT_CODE : 0 (0x0) CHECKPOINT : 0x0 WAIT_HINT : 0x0 PID : 3976 FLAGS :
Now Kill the Service:
taskkill /f /pid 3976
SUCESS: The process with PID 3976 has been terminated.
Check the Windows Application event log, it could contain some entries from your service's auto generated event source (which should have the same name of the service).
For me it was a while loop that looked at an external queue. The while-loop continued running until the queue was empty. Solved it by calling a timer event directly only when Environment.UserInteractive. Therefore the service could be debugged easily but when running as a service it would wait for the timers ElapsedEventHandler event.
Service:
partial class IntegrationService : ServiceBase
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private System.Timers.Timer timer;
public IntegrationService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
// Add code here to start your service.
logger.Info($"Starting IntegrationService");
var updateIntervalString = ConfigurationManager.AppSettings["UpdateInterval"];
var updateInterval = 60000;
Int32.TryParse(updateIntervalString, out updateInterval);
var projectHost = ConfigurationManager.AppSettings["ProjectIntegrationServiceHost"];
var projectIntegrationApiService = new ProjectIntegrationApiService(new Uri(projectHost));
var projectDbContext = new ProjectDbContext();
var projectIntegrationService = new ProjectIntegrationService(projectIntegrationApiService, projectDbContext);
timer = new System.Timers.Timer();
timer.AutoReset = true;
var integrationProcessor = new IntegrationProcessor(updateInterval, projectIntegrationService, timer);
timer.Start();
}
catch (Exception e)
{
logger.Fatal(e);
}
}
protected override void OnStop()
{
try
{
// Add code here to perform any tear-down necessary to stop your service.
timer.Enabled = false;
timer.Dispose();
timer = null;
}
catch (Exception e)
{
logger.Fatal(e);
}
}
}
Processor:
public class IntegrationProcessor
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
private static volatile bool _workerIsRunning;
private int _updateInterval;
private ProjectIntegrationService _projectIntegrationService;
public IntegrationProcessor(int updateInterval, ProjectIntegrationService projectIntegrationService, Timer timer)
{
_updateInterval = updateInterval;
_projectIntegrationService = projectIntegrationService;
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timer.Interval = _updateInterval;
//Don't wait for first elapsed time - Should not be used when running as a service due to that Starting will hang up until the queue is empty
if (Environment.UserInteractive)
{
OnTimedEvent(null, null);
}
_workerIsRunning = false;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
try
{
if (_workerIsRunning == false)
{
_workerIsRunning = true;
ProjectInformationToGet infoToGet = null;
_logger.Info($"Started looking for information to get");
//Run until queue is empty
while ((infoToGet = _projectIntegrationService.GetInformationToGet()) != null)
{
//Set debugger on logger below to control how many cycles the service should run while debugging.
var watch = System.Diagnostics.Stopwatch.StartNew();
_logger.Info($"Started Stopwatch");
_logger.Info($"Found new information, updating values");
_projectIntegrationService.AddOrUpdateNewInformation(infoToGet);
_logger.Info($"Completed updating values");
watch.Stop();
_logger.Info($"Stopwatch stopped. Elapsed seconds: {watch.ElapsedMilliseconds / 1000}. " +
$"Name queue items: {infoToGet.NameQueueItems.Count} " +
$"Case queue items: {infoToGet.CaseQueueItems.Count} " +
$"Fee calculation queue items: {infoToGet.FeeCalculationQueueItems.Count} " +
$"Updated foreign keys: {infoToGet.ShouldUpdateKeys}");
}
_logger.Info($"Nothing more to get from integration service right now");
_workerIsRunning = false;
}
else
{
_logger.Info($"Worker is already running! Will check back again after {_updateInterval / 1000} seconds");
}
}
catch (DbEntityValidationException exception)
{
var newException = new FormattedDbEntityValidationException(exception);
HandelException(newException);
throw newException;
}
catch (Exception exception)
{
HandelException(exception);
//If an exception occurs when running as a service, the service will restart and run again
if (Environment.UserInteractive)
{
throw;
}
}
}
private void HandelException(Exception exception)
{
_logger.Fatal(exception);
_workerIsRunning = false;
}
}
You can try to increase the windows service timeout with a key in the registry
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
"ServicesPipeTimeout"=dword:300000 (300 seconds or 5 minutes)
If it doesn't exists it has to be created.

How to manually run a windows service periodically

I have a windows service that runs every 30 minutes on a server. My boss wants me to add a button in the admin section of the application that runs the service and retrieves current information. This is current code for the service....
protected override void OnStart(string[] args)
{
_stop.Reset();
//30 minutes = 1800000
//5 minutes = 300000
//1 minute = 60000
_registeredWait = ThreadPool.RegisterWaitForSingleObject(_stop,
new WaitOrTimerCallback(PeriodicProcess), null, 1800000, false);
}
protected override void OnStop()
{
_stop.Set();
}
private void PeriodicProcess(object state, bool timeout)
{
if (timeout)
{
// Periodic processing here
}
else
{
// Stop any more events coming along
_registeredWait.Unregister(null);
}
}
You should be able to start a service that isn't running using ServiceController.
using (var sc = new ServiceController("NameOfYourService", "NameOfYourServer"))
sc.Start();

C# Windows Service -- the service on local computer started and then stopped?

I am trying to create my first Windows Service, but so sad... after I started the service manually from services.msc, the message 'the service on local computer started and then stopped. some services stop automatically is they have no work to do'
I am sure there must be some mistake in my code...
namespace ConvertService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
this.ServiceName = "ConvertService";
this.EventLog.Log = "Application";
}
static void main()
{
ServiceBase.Run(new Service1());
}
protected override void OnStart(string[] args)
{
Process pMP3 = new Process();
pMP3.StartInfo.UseShellExecute = false;
pMP3.StartInfo.RedirectStandardOutput = true;
pMP3.StartInfo.FileName = #"d:\...path...\converter.exe";
pMP3.StartInfo.Arguments = #"d:\...path...\tempamr.amr " + #"d:\...path...\tempmp3.mp3 " + #"-cmp3";
pMP3.Start();
pMP3.WaitForExit();
Process pWAV = new Process();
pWAV.StartInfo.UseShellExecute = false;
pWAV.StartInfo.RedirectStandardOutput = true;
pWAV.StartInfo.FileName = #"d:\...path...\converter.exe";
pWAV.StartInfo.Arguments = #"d:\...path...\tempmp3.mp3 " + #"d:\...path...\tempwav.wav " + #"-cwav";
pWAV.Start();
pWAV.WaitForExit();
}
protected override void OnStop()
{
}
}
}
Forgive me if i did silly mistakes. This is my very very first Windows Service.
PS. I have already ticked 'Allow service to interact with desktop'
You didn't create a running thread for the OnStart method. Basically, the service manager calls OnStart to start the service, and that call needs to finish in about 15 seconds or so. Internally, you should create a thread with a loop that actually calls your code over time. Like so:
protected CancellationTokenSource _tokenSource = null;
protected Task _thread = null;
protected override void OnStart(string[] args)
{
_tokenSource = new CancellationTokenSource();
_thread = Task.Factory.StartNew(() => DoMyServiceLogic(), TaskCreationOptions.LongRunning, _tokenSource);
}
protected override void OnStop()
{
_tokenSource.Cancel();
}
protected void DoMyServiceLogic()
{
while(!_tokenSource.Token.IsCancellationRequested)
{
// Do Stuff
}
}
Your service doesn't really follow the pattern; you're not doing things continuously, and that should be more of a console program.
Effectively, it's because your service stopped doing anything as soon as you finished the OnStart method. It's like what happens when you finish Main in a console program - the application just exited.
Check to make sure the account your service runs under can access those files (including write access for the .wav and .mp3 files).
Your code might also be causing an unhandled exception. I'm not sure, but that might be visible in the event log. You can also get your service to write out messages explicitly to the event log (like in the case of an exception); check out this link: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
Open eventvwr.msc. There you will see exception details on why your windows service has stopped working. By the way you should as quickly as possible leave the OnStart method because you only
have 30 seconds to finish the OnStart method.
There is a excellent article on MSDN describing "how to debug" Windows Services.

Windows Service not completely starting

I made this small windows service in c# and I believe I may have done something wrong with my ThreadPool code that prevents my Windows Service from completely starting. If you must know, the windows service seems to be running perfectly only that when looked upon the Services console, it still states that it is "starting". When I restarted my server, the service seem to have stopped again even though I have set it to Automatic startup.
Please see my code below:
protected override void OnStart(string[] args)
{
int itemCount = itemList.Count;
this.doneEvents = new ManualResetEvent[itemCount];
for (int i = 0; i < itemCount; i++)
{
int oId = this.itemList[i];
this.doneEvents[i] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(data =>
{
while (this.activated)
{
DateTime start = DateTime.Now;
// my code here
// choke point
TimeSpan duration = (DateTime.Now - start);
if (duration.Milliseconds < CONST_WAITMILLISECONDS)
Thread.Sleep((CONST_WAITMILLISECONDS - duration.Milliseconds));
}
this.doneEvents[i].Set(); // thread done
}, oId);
}
WaitHandle.WaitAll(doneEvents);
}
You are blocking the OnStart call by WaitHandle.WaitAll(doneEvents);. Windows tries to start the service but times out because of WaitAll.
You need to let OnStart complete if you want Windows to treat the service as started.
I think you could wrap the logic inside OnStart in a thread. This thread would be closed when you received an OnStop event.
Something like this:
Thread _ServiceThread;
protected override void OnStart(string[] args) {
_ServiceThread = new Thread(() => { /* your current OnStart logic here...*/ });
_ServiceThread.Start();
}
protected override void OnStop() {
_ServiceThread.Stop();
}

Categories

Resources