We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Stopping a service thats in a timed loop

wzhxxj
wzhxxj asked
on
Medium Priority
497 Views
Last Modified: 2013-12-03
I have coded an NT service whose function is to send a data string to a network device on a timed interval.  The timed interval is typically set to 30 seconds or more.  My problem is that if an NT service takes longer than 3 seconds to shutdown, the Service Control Manager thinks that the service has stopped responding.  I am using the sleep() function to wait for the specified interval.  If I stop my service from the Services applet in Control Panel while the service is in the sleep state, it typically takes longer than 3 seconds and I get the message, "Service not responding to the control function".  I also tried to use SetWaitableTimer( compiled and linked ok ) but the damn thing would not trigger my function to execute.(??) It seems I have to change my program design a bit but what's the best way to do it.  Should I be using SetWaitableTimer - I've never used it before so anyone with experience, your input is appreciated?
Comment
Watch Question

Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
WDB

Commented:
Use SetTimer() with your specified interval. This will cause no problems and will work every time. Also, your service will shut down correctly whenever it's told to. I have written a service just like yours and I use SetTimer() to control my exporting of data. It works great! This way you won't need to worry about having separate threads. Hope this helps!
xyu

Commented:
WDB... SetTimer???? in NT Service???? i like to see that :)
WDBm have You ever wrote NT service????
WDB

Commented:
I've written many NT services. Many of which are "Back Channel" type "FTP" data transferers. They use SetTimer() extensively. Whats the big secret xyu?????? xyu have You ever written an NT service??????
xyu

Commented:
To WDB.  Excuse me sir, but how You wold like to receive WM_TIMER notification in windowless process?
I wrote as minimum 3 NT services for RealTime Automated Factory Control.
WDB

Commented:
To XYU. Who says I need to receive any WM_TIMER messages?? The timers I use have callback methods. And who says that an NT service has to be windowless?? In fact, I've written at least 2 NT services that interact with the desktop and they both have windows (The topmost level is hidden of course) and icons placed in the system tray!
xyu

Commented:
To allow Your NT service interact with Desktop You have to always run it under SYSTEM account and give permission to interract with desktop... more than that Microsoft recomends that You will make such a services only if You really need it to interact with desktop... !!!! NT Service is windowless by definition... (or recommendation) :)
about WM_TIMER message ok... You can call SetTimer and specify TimeProc callback... but!!!! if Your application doesn't have any message loops i'm not sure You will receive control to that callback... :) as minimum i tried it on console application and never received it :( ...

meanwhile...NT Service it is something that You control via Control Panel/Services ... and with is registered at \\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services and this something survives logout of the user unlike usual application... etc.
I wrote it just to clear definition of NT Service between us :)
WDB

Commented:
To XYU.
1. I agree that if you don't have windows or message loops then using a timer is impossible. However, if you are using windows and messaging loops than there is absolutely nothing wrong with using timers to handle certain tasks.

2. When a service interacts with the desktop it will be available for regular users. This is the reason that I had it interact with the desktop. Most of the time when a regular user is logged on to NT they will NOT have access to the service control manager. I needed to write a service that would be accessable to a regular user (To make supporting our software easier). This service needed to have the ability to be stopped and/or restarted by a regular user in the form of menus and dialog boxes etc.. that would be accessable from the service's icon in the system tray. This would make troubleshooting any problems that might occur with it much easier.

3. I don't agree that a Windows NT Service is windowless by definition, however I do agree that it is so by recommendation. I can tell you that I've gone against Microsoft recommendations in the past and I'm sure I will in the future and I know that I'm not alone in this matter.

4. Back to the original question from wzhxxj. If his service uses message loops and/or windows then, in my opinion, SetTimer() would be the best solution. If he doesn't then the 2 thread approach would be the only other solution. I hope you agree with this xyu :)

WDB

Commented:
To XYU.
1. I agree that if you don't have windows or message loops then using a timer is impossible. However, if you are using windows and messaging loops than there is absolutely nothing wrong with using timers to handle certain tasks.

2. When a service interacts with the desktop it will be available for regular users. This is the reason that I had it interact with the desktop. Most of the time when a regular user is logged on to NT they will NOT have access to the service control manager. I needed to write a service that would be accessable to a regular user (To make supporting our software easier). This service needed to have the ability to be stopped and/or restarted by a regular user in the form of menus and dialog boxes etc.. that would be accessable from the service's icon in the system tray. This would make troubleshooting any problems that might occur with it much easier.

3. I don't agree that a Windows NT Service is windowless by definition, however I do agree that it is so by recommendation. I can tell you that I've gone against Microsoft recommendations in the past and I'm sure I will in the future and I know that I'm not alone in this matter.

4. Back to the original question from wzhxxj. If his service uses message loops and/or windows then, in my opinion, SetTimer() would be the best solution. If he doesn't then the 2 thread approach would be the only other solution. I hope you agree with this xyu :)

xyu

Commented:
I think, that if You need to give user interaction with the service.. You have to give him client application...
What happend if one user forgot to close the service dialog while logging out... and than another user logged in???
will he be able to see the dialog from the previous user?
WDB

Commented:
User interaction will be rare but it needs to be there. The user interaction consists of stopping the service, restarting the service and viewing an error log. The only dialog that could remain visible would be the error log dialog. As you can see, the situation that you stated, or any other situation for that matter, will never cause a problem with this service. The services I've created have been running for over a year and they have been practically flawless. There have only been 2 or 3 cases where the user interface needed to be used and we have hundreds of users using the service 1000's of times a day. Managing a service is a heck of a lot easier than having to worry about a client app. The ability to have windows etc.. in a service is there for a reason!!

Author

Commented:
Xyu, if I set ServiceStatus.dwWaitHint to 30 seconds or more, then I am sure that after this interval, my service probably would have exited the sleep() function and stopped without an error from the SCM.  

I found a better way.  I used the WaitForSingleObject() with a timeout of 30 and supplied it the handle of my service stop event object, which I created.  My service thread consumes very little processor time while waiting for the event object state to become signaled or the time-out interval to become elapsed. When running, the WaitForSingleObject()function would continually timeout, giving me my 30 second timer.  When I stopped my service, I signaled the service stop event object with SetEvent() which causes my WaitForSingleObject() function to return, thereby terminating my timer immediately.  This allowed me to shut my service down without putting any delays in it.  Works beautifully and I didn't need multi-threads.

The comments I received from xyu and wdb were great.  Both of you guys obviously have a lot of experience with coding services.
ps: I also tried using SetTimer with a callback function but that didnt't work - probably because my app is windowless and doesn't use message queues.(?)
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.