I have created a win32 application that should be run as a service and as an application. When I click and run it, It should run as an application. when called from service controller, It should detect being it and branch to run as a service. How do I detect this, without passing arguments? mr.abzadeh
-
I don't know how to do it without command line args, but why do you need it? – Iłya Bursov Oct 08 '15 at 18:54
-
You have to have some state to determine what you use to branch on. I've always used command line arguments. But you could use an environment variable, registry key setting, presence of a debugger, etc. – josh poley Oct 08 '15 at 19:46
-
I don't use command line arguments because It's hard for my users to supply it. The want to click and run it. And I don't know how to pass argument to a service – MR_ABDOLAHZADEH Oct 10 '15 at 06:34
-
Just [pass a parameter like `/service` when running as a service](http://stackoverflow.com/questions/6490979/how-to-pass-parameters-to-windows-service). – Raymond Chen Oct 11 '15 at 02:39
-
@RaymondChen, that requires the user to add the parameters explicitly each time the service is started. [This answer](http://stackoverflow.com/a/2243873/886887) is probably more apropros, though I can't personally vouch that it works. – Harry Johnston Oct 11 '15 at 21:56
-
@HarryJohnston You only need to set the parameters when the service is installed. And hopefully, your installer does that; users shouldn't be installing services manually. A program that changes its behavior based on an autodetected execution environment is very hard to debug. – Raymond Chen Oct 11 '15 at 22:43
-
@RaymondChen: the idea is sound, it's just that none of the answers to the particular question you linked to set the permanent parameters, only the temporary ones. (And I'm not sure whether that OP *wanted* a solution where the parameters were permanently set or not, the question is a bit ambiguous.) – Harry Johnston Oct 11 '15 at 22:59
-
Actually my link isn't much better, since it's for C# and this OP is using C. :-) In C, you can simply include the parameters as part of the lpBinaryPathName argument to the CreateService() funtion. – Harry Johnston Oct 11 '15 at 23:01
-
(For reference, the service receives permanent parameters via the main function, and temporary parameters via the ServiceMain function. This behaviour is not very well documented.) – Harry Johnston Oct 11 '15 at 23:04
1 Answers
The traditional (and simplest) approach is to call StartServiceCtrlDispatcher() and, if it fails, assume that you are not running as a service. This works well in practice, although technically I do not believe Microsoft guarantees that it will do so.
If you want a more robust approach, you could examine your security token to see whether or not it contains the Service SID, S-1-5-6. However, in order for this to work, you must ensure that the service is configured with a non-zero SID type, i.e., with either SERVICE_SID_TYPE_UNRESTRICTED
or SERVICE_SID_TYPE_RESTRICTED
.
Note: I'm attempting to answer the question as written, but a better solution is to set a command-line parameter as discussed in the comments. You can include command-line parameters in the lpBinaryPathName
argument to CreateService(). Your main() function will receive these parameters in the same way as an ordinary commmand-line application.

- 35,639
- 6
- 68
- 158
-
Thanks for your reply. I prefer to examine security token. As the link you directed me, I call ConvertStringSidToSId to get PSID of S-1-5-80-0, then call the following this(simplified); OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); GetTokenInformation(hToken, TokenGroups, nullptr, 0, &dwSize); GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSize, &dwSize); Then I scan pGroupInfo->Groups. I install the service and log Groups. But I never get SID, S-1-5-80-0; the only SIDs I get is S-1-5-32-544, S-1-1-0, S-1-5-11, S-1-16-16384; Can you please tell my where I am wrong? – MR_ABDOLAHZADEH Oct 10 '15 at 15:25
-
OK, two problems: firstly, I'd given you the wrong SID; it should have been S-1-5-6, not S-1-5-80. Secondly, it seems this only works if the service is configured with a non-zero SID type. I've updated the answer accordingly. Note that you can set the SID type (when installing the service) using the ChangeServiceConfig2() function. – Harry Johnston Oct 11 '15 at 00:33
-
I Set the service sidtype to unrestricted and restricted using SC.exe, and not got the SID. Can you please offer me a reference link about this? Thanks for your Help. – MR_ABDOLAHZADEH Oct 11 '15 at 19:51
-
As far as I know the links in the question constitute all the documentation available. :-( Have you tried rebooting the machine after changing the sidtype? (Shouldn't be necessary, but you never know.) Can you post the logging code you're using? (If I can't see the problem, I'll try it myself and see if I can build some working code to post.) – Harry Johnston Oct 11 '15 at 22:01