Archive: Service : DisplayName / ServiceName


Service : DisplayName / ServiceName
Hi,

I would like to create a service with a displayname different than the servicename, and a particular description.

In my company, the guy who was doing installation quit and I've to take his script and modify them.

I'm using this to create the service

!insertmacro SERVICE "create" "$R2" \
"path=$R3;type=$R4;interact=$R5;display=$R6;machine=$R7;user=$R8\$R9;password=$0;desc=$1;"


But description, display name and interact doesn't work. Type doesn't work either.

To modify the type, i've to do :

WriteRegDWORD HKLM \
"SYSTEM\CurrentControlSet\Services\${PRODUCT_SHORT_NAME}-${PRODUCT_VERSION}-gas-$R6" \
"Start" 0x00000002


To modify description, i'm doing this :

WriteRegStr HKLM \
"SYSTEM\CurrentControlSet\Services\${PRODUCT_SHORT_NAME}-${PRODUCT_VERSION}-gas-$R6" \
"Description" "Manages Genero applications on the server and their connectivity \
with remote ActiveX and WebServices"


To start the create service :

!insertmacro SERVICE "start" \
"${PRODUCT_SHORT_NAME}-${PRODUCT_VERSION}-gas-$R6" ""


All of theses "tricks" work for me (even I'm sure there are far better way to do that).

Now I want to modify the display name :

WriteRegStr HKLM \
"SYSTEM\CurrentControlSet\Services\${PRODUCT_SHORT_NAME}-${PRODUCT_VERSION}-gas-$R6"\
"DisplayName" "Genero Application Server (GEP)"


The registry's datas are up-to-date, but in the Services administration tools, it's the servicename that is displayed AND in the property window of the service, the display name is good.

I've tested on w2k and wxp for the same result

So i'm quited confused on how can i achieve to create the desired service.

I've read about SC.exe but can't find it on my w2k computer.

I've also see this in archive Service Control Manager plugin but don't know how to use it.

Can someone help me ? Thx !!

Geoffrey

Are you sure what you're trying to do is possible? If it does display the name you want in the property page, but doesn't display it in the service list, it's possible that's just how it works.


Yes, it's possible to have a displayname different form the service name, but the problem comes from Windows in fact.

If I restart the computer, the service display name is correctly updated in the services windows.

What is weird is that the property windows of the service doesn't need a restart to be correctly displayed whereas the services windows need a restart to take in account the datas from the registry !

I should find a way to specify displayname and servicename at the service creation, and not modify it by editing the registry keys later, any idea ?

Geo


If restarting the computer updates the name, Windows probably doesn't read the name from the registry after you write it. I'm sure there is an API function for quite a simple usage. Search MSDN for methods to update the name of a service. If you can find something but can't get it to work with the System plug-in, post the details and someone will surely be able to help you.


Hello,

I have the same need as geoffrey_4js and i think i use the same library to create a NT service (servicelib.nsg from dselkirk).
What i have seen in this library is that the same value is used to create the service name and the service displayname, instead of hard coding the value i wanted to add a variable but didn't manage (i discover NSIS for a week and not a real developper).
I'll try to contact dselkirk if he can make a change to his code, but if anyone has a clue !
Thanks in advance...

The library used :
http://nsis.sourceforge.net/NSIS_Service_Lib

The code to create the service in the library :

System::Call 'advapi32::CreateServiceA(i r4, t r2, t r2, i ${SERVICE_ALL_ACCESS}, \
i R4, i R5, i 0, t R6, n, n, R1, R2, R3) i.r6'

Detail of the API function :
CreateServiceA( DWORD hSCManager, LPCSTR lpServiceName,
376 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
377 DWORD dwServiceType, DWORD dwStartType,
378 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
379 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
380 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
381 LPCSTR lpPassword )

I guessed variable r2 is used to create service name AND displayname...


Reading this MSDN page it seems to me that the second parameter controls the service name while the third parameter controls the display name (to be used by user interface programs to identify the service).

instead of hard coding the value i wanted to add a variable but didn't manage
Can you provide the code that you used?
CF

I agree with you that the 2nd parameter stands for 'service name' and 3rd for the 'displayname'.
The fact is that the library i use takes the same variable for both of them.

Part of my nsi script:

Section -post SEC0001
...
!insertmacro SERVICE "create" "MyServiceName" "path=$INSTDIR\SubDir\MyService.exe;autostart=1;"
...
SectionEnd


what the macro does (full lib at http://nsis.sourceforge.net/NSIS_Service_Lib):

Parsing the 3 parameters given "action" "name" "parameters"

Then

System::Call 'advapi32::CreateServiceA(i r4, t r2, t r2, i ${SERVICE_ALL_ACCESS}, \
i R4, i R5, i 0, t R6, n, n, R1, R2, R3) i.r6'

i'd like to add another parameter/variable in "parameters" in order to define a different variable for the parameter "displayname" instead of using the same param or hard coding it in the lib like :

System::Call 'advapi32::CreateServiceA(i r4, t r2, t "MyDisplayNameString", i ${SERVICE_ALL_ACCESS}, \
i R4, i R5, i 0, t R6, n, n, R1, R2, R3) i.r6'

What i would like :

Section -post SEC0001
...
!insertmacro SERVICE "create" "MyServiceName" "path=$INSTDIR\SubDir\MyService.exe;autostart=1;display=My Service Display Name;"
...
SectionEnd

System::Call 'advapi32::CreateServiceA(i r4, t r2, t rX, i ${SERVICE_ALL_ACCESS}, \
i R4, i R5, i 0, t R6, n, n, R1, R2, R3) i.r6'


I hope it is clear :igor: , however you have the link to the full code of the lib ! ;)

(Wow!! longer post than expected, nobody bothered ?...)


Since you only need to use the Display name upon the creation of the service there is no reason to alter the header that you are using, just get a handle to the service manager, create your service, and use the servicelib header for anything else (including uninstalling the service).
Something like this:

...
!define SC_MANAGER_ALL_ACCESS 0x3F
!define SERVICE_ALL_ACCESS 0xF01FF

; Service Types (SRVType)
!define SERVICE_FILE_SYSTEM_DRIVER 0x00000002
!define SERVICE_KERNEL_DRIVER 0x00000001
!define SERVICE_WIN32_OWN_PROCESS 0x00000010
!define SERVICE_WIN32_SHARE_PROCESS 0x00000020
!define SERVICE_INTERACTIVE_PROCESS 0x00000100

; Service start options (SRVStartOptions)
!define SERVICE_AUTO_START 0x00000002
!define SERVICE_BOOT_START 0x00000000
!define SERVICE_DEMAND_START 0x00000003
!define SERVICE_DISABLED 0x00000004
!define SERVICE_SYSTEM_START 0x00000001

; Service Error control (SRVErrorControl)
!define SERVICE_ERROR_CRITICAL 0x00000003
!define SERVICE_ERROR_IGNORE 0x00000000
!define SERVICE_ERROR_NORMAL 0x00000001
!define SERVICE_ERROR_SEVERE 0x00000002

!macro CreateServiceEx SRVName DisplayName SRVType SRVStartOptions SRVErrorControl SRVExecutable SRVUser SRVPasswd
System::Call 'advapi32::OpenSCManagerA(,,i ${SC_MANAGER_ALL_ACCESS})i.R0'
System::Call 'advapi32::CreateServiceA(i R0,t "${SRVName}",t "${DisplayName}",i ${SERVICE_ALL_ACCESS},i ${SRVType}, \
i ${SRVStartOptions},i ${SRVErrorControl}, t "${SRVExecutable}",,,,t "${SRVUser}",t "${SRVPasswd}")i.r1'
System::Call 'advapi32::CloseServiceHandle(i R0) n'
!macroend

...
And to use it, call it from within your code:
!insertmacro CreateServiceEx "ServiceName" "My Fancy Service Name" ${SERVICE_FILE_SYSTEM_DRIVER} ${SERVICE_BOOT_START} ${SERVICE_ERROR_IGNORE} "$SYSDIR\SomeFile.sys" "" ""

The last two parameters control the username and password that will be used to run the service. If you leave them both empty then the LocalSystem account is used. Check this MSDN pages for more info ...

I have not tested the above but it should work. Use the servicelib header to uninstall/query/control the service and the above macro to create it

:)

CF

[Edit] @%@#$ forgot all the definitions!

Thanks for the job and time passed to help.
I may try this but maybe i m stupid but i don't know why rewrite function createservice when the lib is ready to do that and you just have to change/add a parameter to define this displayname value.

One more question : what are those parameters r4, r2 (different from $RX in lib ?) and what are those letters in front of them (i, t ?)...


Well I didn't rewrite the entire thing, I just created a small macro that achieves what you were after. Saves me the trouble of troubleshooting the rest of the code too! You will still need to use the servicelib for the rest of the functions that it provides. :)

One more question : what are those parameters r4, r2 (different from $RX in lib ?) and what are those letters in front of them (i, t ?)...
You may want to read the documentation of the System plugin to get an idea about those ... ;)

CF

Ok CF, thank you for all the precious information

Edit : i read the System plug-in readme and it is beyond my reach :( I hope i'll never have to use it by myself :hang:


I've released my modified version of servicelib.nsh.

I removed some bugs and added this feature as I also want to display an arbitrary name for a service.

Hope this helps...

++Vitoco


You should update the Wiki page with the new version. If not backward compatible, at least as another version. But as far as I can see, it can be easily made backwards compatible by accepting both "machine" and "depend".

This will assure future generations will find it easily and won't run into the trouble you've already fixed.


I'm not the author of that piece of code, I just fixed it. I sent an email to dselkirk some time ago without a response. This is why I wrote my page instead of to update the wiki.

Accepting both parameters ("machine" and "depend") is a good idea for backward compatibility, but I'm not sure if "machine" was once used as the name of the machine where to install a service. I don't know about Windows' system calls history :D

If I get some requests here, I'll think again about to upload my script to the wiki.

++Vitoco


The Wiki is all about public contribution. You can edit that page, even if you didn't create it. If you have a fix for a script in the Wiki, you should update the page to at least mention it. In the worst case, there's an history page for each Wiki page.


Version 1.4 of ServiceLib.nsh available
Wiki page updated...

The new 1.4 version is backward compatible (accepts both "depend" and "machine" as the name for the same parameter).

++Vitoco