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.
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.
Situation
There's a windows service given and I want to implement something like an auto-update feature. For this case I call another executable file which handles the update process.
public partial class Main : ServiceBase
{
public Main()
{
InitializeComponent();
TryUpdate();
/* Some Extra Code */
}
private void TryUpdate()
{
Process proc = new Process();
proc.StartInfo.FileName = #"UpdateCheck.exe";
proc.Start();
proc.WaitForExit();
if (proc.ExitCode != 0)
{
Process proc2 = new Process();
proc2.StartInfo.FileName = #"UpdateCheck.exe";
proc2.StartInfo.Arguments = "Update";
proc2.Start();
/* Here is where I want the application to quit! */
throw new Exception();
}
}
protected override void OnStart(string[] args)
{
/* Some Extra Code */
base.OnStart(args);
}
}
When I call the TryUpdate-Function, it starts another process which determines if there's an update available or not. If there is one, I call the process again with the parameter to update the service (it basically just waits for a few seconds so that the service can shut down and then uninstalls and installs the service using an installshield setup).
Obviously it is not the smartest solution. The problem I am facing now though is the following:
When I throw an Exception to stop the service from starting (I guess?) the application crashes and tells me the service did not respond in a timely fashion (Error 1053).
Actual Question
How do I cancel a windows service properly at this state?
I have windows service that is multi-threded, the threads contains while loop that should always be activated,socket thread which send errors from my other application that installed there, thread which initialize few timers
when i start the thread its start for few sec, then throw exception which says that my service stopped working and ask to send the data to Microsoft.
i don't know what make my service do it, probably the threads but i don't understand what wrong with my implementation
in addition i use custom installer, when the user start the application it will install the service.
tools is a class which contains static mathods.
my code:
public partial class MyService : ServiceBase
{
public static System.Timers.Timer key;
public static System.Timers.Timer browse;
public static System.Timers.Timer sender;
// array of worker threads
Thread[] workerThreads;
public MyService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
workerThreads = new Thread[]
{
new System.Threading.Thread(new ThreadStart(InitTimers)),
new System.Threading.Thread(new ThreadStart(Tools.CheckApplication)),
new System.Threading.Thread(new ThreadStart(Tools.CheckBrowser)),
new System.Threading.Thread(new ThreadStart(Tools.SendOnError))
};
// start the threads
for (int i = 0; i < workerThreads.Length; i++)
{
workerThreads[i].Start();
}
}
protected override void OnStop()
{
}
public void InitTimers()
{
key = new System.Timers.Timer();
key.Interval = 1;
key.Elapsed += Other.key_Tick;
key.Enabled = true;
browse = new System.Timers.Timer();
browse.Interval = 1;
browse.Elapsed += Other.browse_Tick;
browse.Enabled = true;
sender = new System.Timers.Timer();
sender.Interval = 3600000;
sender.Elapsed += Other.sender_Tick;
sender.Enabled = true;
key.Start();
sender.Start();
browse.Start();
}
}
EDIT:
if i found the right log the exception is this:
The thread tried to read from or write to a virtual address for which it does not have the appropriate access.
never saw it... from what the exception coming from and why?
p.s the log is the log that suppose to be sent to Microsoft, i didnt create event log so i don't think i have one
I guess from your code that you are accessing the browser on the desktop.
See How can I configure my windows service in the code to access the desktop?
Read both answers, one tells you how to enable access, the other one strongly suggests another design (client app that interacts with the service)
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();
}