Windows service: How to cleanup with a NOP OnStop() - windows

A windows service program is implemented by deriving from ServiceBase class with C#. The service will load an assembly with a background thread in OnStart() and start from a function entry point through an InvokeMember() call. Inside the assembly dll/background thread, the program will allocate various system resources during its running. Now the problem is that the OnStop() implemented as a NOP, so there is no hook I can use. Without changing the OnStop() implementation, how do I clean up allocated resources when the service is stopped by "sc stop aService"?
I tried various ways but looks like there is no way to intercept "sc stop" message besides changing OnStop(). I tried to add a try/catch/finally block with a backgroud cleanup thread but I can't get the finally clause called. Tried AppDomain UnhandledException and ProcessExit handlers and that did not do anything either. So what're the effects of a SERVICE_CONTROL_STOP(sc stop) on background threads? Is there anyway I can clean up resources within my assembly/dll at all?

Related

How global SetWindowsHookEx manages to inject dll into all threads?

I created 2 hooks in my host application. 1st is WH_MOUSE set specifically for Taskbar's thread. 2nd is global WH_KEYBOARD_LL hook (dwThreadId is set to 0).
As you can see in Process Explorer, the "local" hook actually injected my dll into specific explorer.exe thread. However, there is no indication that my 2nd global hook got injected into any other processes, yet it still works perfectly... Moreover, it also works for all the new processes I start, even after the hook was set! How SetWindowsHookEx manages that?
I read that it only applies to processes that load user32.dll. My weak suspicion is that in a case of global hook, Windows somehow injects my custom dll code into user32.dll "hook-chain". And then, when new process that loads user32.dll is started, it automatically loads my hook with it? Is this correct or is there some other mechanism at work?
_LL (low-level) hooks are not injected anywhere, win32k (the kernel part of the window manager) calls the hook callback function directly. This is why that thread needs a message loop. Low-level hooks are always "global".
MSDN says:
Be aware that the WH_MOUSE, WH_KEYBOARD, WH_JOURNAL*, WH_SHELL, and low-level hooks can be called on the thread that installed the hook rather than the thread processing the hook.
You should think of hooks as having 3 modes:
Low-level (keyboard and mouse only)
Thread specific
All threads
The last two might require Windows to inject the .dll.

CefCharp causing program termination to halt

My program has decided to stop terminating when it is done.
The program is spawned by a service, The Main() function calls some external classes I created which make some PDFs and then terminates with a Return. There are no forms, no UI. This has worked for years.
I have now tried End, Application.Exit() and Environment.Exit(0)
I just added some functionality using CefCharp to one of the external classes the program uses and as part of that I have added some Async functions and Awaits to this class. As far as I can tell I am Dispose()ing each instance of the CefSharp browser I am creating. I am also calling CefSharp.Cef.Shutdown() at the end of the same function that calls CefSharp.Cef.Initialize(). All Awaits appear to be returning fine so I don't think I am leaving any threads hanging.
So it turns out that putting CefSharp.Cef.Shutdown() at the end of the same function that initializes it and does most of the work does not seem to be adequate or maybe it is still busy and not ready for shutdown?
So I put another CefSharp.Cef.Shutdown() in my classes' Dispose() method. Now my program terminates properly.

ExitProcess behaviour in Windows in relation to atexit handlers

I want to be able to catch any attempts of executing exit()/ExitProcess()/TerminateProcess() or any other such calls.
I thought about registering a handler with atexit(). This works fine for normal program termination (return from main()) or exit() calls (regardless of the thread that calls exit()), but ExitProcess() and TerminateProcess() bypass the handler I registered.
ExitProcess() documentation states:
Note that returning from the main function of an application results
in a call to ExitProcess.
But the observed behaviour is at least different in this regard.
Is there a method of registering a handler for process exit/termination what will always be called (except for external calls to TerminateProcess(), unhandled exceptions thrown by one of my threads or __failfast() calls, I'm guessing these are really impossible to catch).
There is the dirty option of hooking ExitProcess(), but I'd rather not do that.
EDIT: just so this is clear: I'm interested in my own process, not monitoring / controlling another process.
There is a Kernel Mode Event a device driver can subscribe to in order to get notifications of terminations of processes. This is preferred over trying to inject a DLL into processes for API hooks due to the myriad number of internal and external ways that process may end.

Windows Service execute logic after OnStart

I have a Windows Service which has several timer jobs in it. In the OnStart method, I am starting all those timers. In effect, it takes a lot of time starting the service from the Services console and most of the time, it reports this:
Windows could not start the 'servicename' service on Local Computer.
The service did not repond to the start or control request in a timely fashion.
I know I could create a timer which encapsulatesthe other timers so I could start them outside the OnStart event. However, I'm looking for other possible solutions as I don't like the idea of having a separate timer which does nothing other than start the other processes.
It isn't generally safe to perform external operations such as web or database calls during OnStart, because you can't predict how long they will take, and an excessively long service startup time can interfere with the system:
The Service Control Manager (SCM) waits until the service reports a status of SERVICE_RUNNING. It is recommended that the service reports this status as quickly as possible, as other components in the system that require interaction with SCM will be blocked during this time. Some functions may require interaction with the SCM either directly or indirectly.
So the proper solution is to move this initialization into a separate thread.
However, if you don't want to do this, you can call RequestAdditionalTime:
The RequestAdditionalTime method is intended to be called by the overridden OnContinue, OnPause, OnStart, or OnStop methods to request additional time for a pending operation, to prevent the Service Control Manager (SCM) from marking the service as not responding.

What's the difference between OnStop() method and Stopping event in Windows Azure role?

Whenever a Windows Azure role is stopped its OnStop() method is invoked. Turns out that there's RoleEnvironment.Stopping event that is triggered before OnStop() is invoked. MSDN says this event is the right place for role clean shutdown code.
What's the difference between the two? Why would I put role clean shutdown code in Stopping event and not in OnStop() method override?
Besides the fact that the event mechanism provides a flexible way to attach handlers, while the OnStop method has to be defined directly on the class derived from RoleEntryPoint, one relevant difference is this:
The Stopping event is not raised when the virtual machine of the role
instance is rebooted.
So the stopping event will not be raised, for instance, when the VM is rebooted for guest OS upgrade.
Another difference is this:
Code running in the OnStop method has 5 minutes to finish when it is called
for reasons other than a user-initiated shutdown.
While there is no mention in the documentation that the Stopping event has such a limit.
Source:
MSDN - RoleEnvironment.Stopping Event
MSDN - RoleEntryPoint.OnStop Method
Events allow other subscribers in other classes to perform some action, whereas the method allows the subclass author such as yourself to place it in the actual class and (for example) modify which events get raised.
Brent Stineman (Windows Azure MVP) recently blogged about the RoleEntryPoint and related start/run/stop sequence, and describes both Stopping and OnStop in the sequence descriptions.

Resources