Open davidfowl opened 5 years ago
Example implementation: https://github.com/aspnet/Extensions/pull/1369/files
@anipik owns this area. Why is the API useful?
We use it in our hosting layer to make the windows service specific logic noop. The benefit being that we can light up specific behavior when running in that context (like hooking into the lifetime events). This means my application runs in both modes (service or self hosted) seamlessly.
We’ve also had a customer ask us for this logic because they wanted a change to write some service specific logic in their startup.
@anurse is that method documented, eg there is some reason to believe the service host process name won't change in future Windows versions?
I don't feel strongly but Im inclined to think we would want more evidence of need. If it was wrapping something like ::IsAService()
it would be a lower bar in my mind.
I just described how we use it. What evidence are you looking for? Are you not convinced that there are scenarios where knowing that you are running in a windows service is useful?
If windows changes it in the future we’ll update the code. If you know of a better way to detect that scenario there’ll be no pushback
I believe this would be useful. In the past I've hooked up a log reader if running outside a service so I can direct the output to a user interface.
if this was on ServiceBase the app would require a reference to the compat pack which it might not otherwise need. On the flip side, it is very Windows specific...
@danmosemsft do yo have a proposal? Where would it live?
There is Environment.UserInteractive which checks if the application is running in an "Interactive Session".
From the docs:
The UserInteractive property reports false for a Windows process or a service like IIS that runs without a user interface. If this property is false, do not display modal dialogs or message boxes because there is no graphical user interface for the user to interact with.
In my initial cursory testing, a console app reports Environment.UserInteractive
as true
.
We might need further testing here, but it may serve our purpose. It's not guaranteed to indicate that you're in a Windows Service though since there may be other non-Windows Service non-Interactive scenarios.
That would also include scheduled tasks.
That's what I was looking for :). I figured there might be a counter-example here.
Doesn't that also report true when running in IIS?
As an aside, I had a quick look at the service related Win32 API and I didn't see an alternative way to check the current process is a service. The API's all deal with handles or service names (from which you get the handle). I don't see a way eg to enumerate services from a process handle.
Ideally we could get hold of the services parent process by a more robust method than using its name, but I don't know how.
Name+path(%SystemRoot%\System32\services.exe
)+Environment.UserInteractive
?
Another idea could be check associated windows station name, from Windows Internals 6
:
Unless other directed, the Windows subsystem associates services running in the local system account with a nonvisible windows station named Service-0x0-3e7$ that all noninteractive services share.
...
However only processes owned by the system and Windows services run in session 0; all other logon sessions, including those of console users, run in different session. Any windows displayed by process in session 0 is therefore not visible to the user.
Check for Service-0x
+ login session identified + $
I did some check and it works also under IIS
The only issue is in case of SERVICE_INTERACTIVE_PROCESS
flag for LocalSystem account...process will be associated with WinSta0, this is however not recommended for security reason and supported for backward compatibility.
@Anipik @maryamariyan please limit 3.0 milestone to issues that must be fixed to ship 3.0.
Conclusion
ServiceBase
ServiceBase
is not desirable.IsRunningAsService
as Windows is implied (the entire type is Windows-specific)There are more questions. It seems someone needs to sit down and go through the Windows SCM APIs to see how this can be made reliable. There is also the question whether we need an API to return this for other processes, and not just the current one. Windows also allows hosting multiple services in a single process.
We also need to decide what, if any, the cross-platform angle is. For example, Windows might support multiple services by a single process. Daemons might not. It seems safer to scope this API to be Windows-only. However, it means we shouldn't burn a name like Process.IsRunningAsService
, for instance.
Environment.UserInteractive
always returns true
in .NET Core. Maybe, while at it, you could properly implement this API as well?
@george-chakhidze yep, this was done for 5.0. And as was pointed out above, it is not the same as this proposed API, although for some use cases it may be enough.
In C++, I just call StartServiceCtrlDispatcher, and if that fails with ERROR_FAILED_SERVICE_CONTROLLER_CONNECT, then I know I'm not running as a service.
The equivalent thing was not feasible to implement on .NET Framework because ServiceBase.Run would handle the error by popping up a Windows Forms message box. That was removed in the .NET Core port but the method still logs the error to the console and to event logs.
We recently added an API to detect if a .NET process was being lauched as a windows service (https://github.com/aspnet/Extensions/pull/1369). I believe this belongs in SeviceBase as it would be useful to have this feature outside of our hosting wrapper.
I'm open to other names.
cc @danmosemsft