Talk:NSIS Service Lib: Difference between revisions
m (→Usage Examples) |
m (replaced <pre> with <highlight-nsis>) |
||
(4 intermediate revisions by 2 users not shown) | |||
Line 238: | Line 238: | ||
---- | ---- | ||
== Error in lbl_description == | |||
The line | |||
strcmp $R7 "error" 0 lbl_descriptioncomplete | |||
after label lbl_description is incorrect. ChangeServiceConfig2 returns a boolean. Thus you have to change it to | |||
strcmp $R7 0 0 lbl_descriptioncomplete | |||
Claus Henning ([[Special:Contributions/195.226.184.202|195.226.184.202]]) 12:33, 6 January 2011 (UTC) | |||
== Added function: waitfor == | |||
I added a function to servicelib that waits for the service to reach a specific state. This function takes two parameters: | |||
; status | |||
: Can be ''running'', ''stopped'' or ''paused'' and specifies for which state the function should wait. | |||
; timeout | |||
: Specifies the maximum time to wait (in seconds). It the timeout is reached before the service enters the desired state, "timeout" is returned in ''$0'' | |||
<highlight-nsis> | |||
lbl_waitfor: | |||
!insertmacro CALL_GETPARAM $7 "status" "n" "lbl_done" ; $7 is status as string | |||
StrCpy $8 ${SERVICE_RUNNING} ; $8 is status as hex int | |||
StrCmp $7 "running" lbl_waitforstatus | |||
StrCpy $8 ${SERVICE_STOPPED} | |||
StrCmp $7 "stopped" lbl_waitforstatus | |||
StrCpy $8 ${SERVICE_PAUSED} | |||
StrCmp $7 "paused" lbl_waitforstatus | |||
StrCpy $0 "false" ; illegal parameter "status" | |||
Goto lbl_done | |||
lbl_waitforstatus: | |||
!insertmacro CALL_GETPARAM $9 "timeout" "30" "lbl_waitfortimeout" ; $9 is timeout in seconds | |||
lbl_waitfortimeout: | |||
Push $R1 ; SERVICE_STATUS structure | |||
StrCpy $0 "timeout" ; in case we reach timeout | |||
lbl_waitforloop: | |||
Sleep 1000 | |||
System::Call '*(i,i,i,i,i,i,i) i.R1' | |||
System::Call 'advapi32::QueryServiceStatus(i r5, i $R1) i' | |||
System::Call '*$R1(i, i .r6)' ; $6 is now service status from QueryServiceStatus() | |||
System::Free $R1 | |||
IntOp $9 $9 - 1 | |||
StrCmp $9 0 lbl_done ; timeout reached | |||
IntFmt $6 "0x%X" $6 | |||
IntCmp $6 $8 0 lbl_waitforloop lbl_waitforloop | |||
Pop $R1 | |||
Goto lbl_good | |||
</highlight-nsis> | |||
I hope you find this useful, however it's up to you to add it to the 'official' library. I just wanted to contribute my work because your library has helped me a lot! | |||
--[[User:Christifuzius|Christifuzius]] 14:51, 10 January 2012 (UTC) |
Latest revision as of 14:53, 10 January 2012
I noticed that I couldn't create an "interactive" service using your otherwise excellent lib...here's the fix!
Old code:
199 !insertmacro CALL_GETPARAM $R4 "interact" "0x10" "lbl_interact" 200 StrCpy $6 0x10 201 IntCmp $R4 0 +2 202 IntOp $R4 $6 | 0x100 203 StrCpy $R4 $6 204 lbl_interact:
New code:
199 !insertmacro CALL_GETPARAM $R4 "interact" "0x10" "lbl_interact" 200 StrCpy $6 0x10 201 IntCmp $R4 0 +2 202 IntOp $6 $6 | 0x100 203 StrCpy $R4 $6 204 lbl_interact:
The (very slight) change is on line 202.
Thanks again,
Nathan Probst
- You're correct. I've applied the fix, thanks.
- --kichik 09:12, 5 January 2006 (PST)
There is a tiny bug that makes the original registers swapped after the function Old code:
321 Pop $5 322 Pop $6 323 Pop $7 324 Exch $0 325 !macroend
New code:
321 Pop $5 322 Pop $7 323 Pop $6 324 Exch $0 325 !macroend
--Charlesb 05:25, 22 February 2006 (PST)
- Correct. I've applied the fix, thanks.
- --kichik 10:34, 23 February 2006 (PST)
I use this patch to avoid some possible quote problem and that add a setdesc to set description (CreateService threat empty dependencies and empty password as NULLs) Also I used some Unicode versions instead of ANSI
--- C:\myprog\srv\PopupService\installer\mao.nsh Thu Dec 14 15:27:41 2006 +++ C:\myprog\srv\PopupService\installer\servicelib.nsh Thu Dec 14 15:25:31 2006 @@ -20,10 +20,11 @@ ; interact - interact with the desktop ie. 1|0 ; depend - service dependencies ; user - user that runs the service ; password - password of the above user ; display - display name in service's console +; setdesc - set service description ; ; delete - deletes a windows service ; start - start a stopped windows service ; stop - stops a running windows service ; pause - pauses a running windows service @@ -164,11 +165,11 @@ StrCpy $0 "false" System::Call 'advapi32::OpenSCManagerA(n, n, i ${SC_MANAGER_ALL_ACCESS}) i.r4' IntCmp $4 0 lbl_done StrCmp $3 "create" lbl_create - System::Call 'advapi32::OpenServiceA(i r4, t r2, i ${SERVICE_ALL_ACCESS}) i.r5' + System::Call 'advapi32::OpenServiceW(i r4, w r2, i ${SERVICE_ALL_ACCESS}) i.r5' IntCmp $5 0 lbl_done lbl_select: StrCmp $3 "delete" lbl_delete StrCmp $3 "start" lbl_start @@ -176,10 +177,11 @@ StrCmp $3 "pause" lbl_pause StrCmp $3 "continue" lbl_continue StrCmp $3 "installed" lbl_installed StrCmp $3 "running" lbl_running StrCmp $3 "status" lbl_status + StrCmp $3 "setdesc" lbl_setdesc Goto lbl_done ; create service lbl_create: Push $R1 ;depend @@ -187,25 +189,24 @@ Push $R3 ;password Push $R4 ;interact Push $R5 ;autostart Push $R6 ;path Push $R7 ;display + Push $R8 ;user type - !insertmacro CALL_GETPARAM $R1 "depend" "n" "lbl_depend" - StrCpy $R1 't "$R1"' + !insertmacro CALL_GETPARAM $R1 "depend" "" "lbl_depend" lbl_depend: - StrCmp $R1 "n" 0 lbl_machine ;old name of depend param - !insertmacro CALL_GETPARAM $R1 "machine" "n" "lbl_machine" - StrCpy $R1 't "$R1"' + StrCmp $R1 "" 0 lbl_machine ;old name of depend param + !insertmacro CALL_GETPARAM $R1 "machine" "" "lbl_machine" lbl_machine: + StrCpy $R8 "n" !insertmacro CALL_GETPARAM $R2 "user" "n" "lbl_user" - StrCpy $R2 't "$R2"' + StrCpy $R8 "w R2" lbl_user: - !insertmacro CALL_GETPARAM $R3 "password" "n" "lbl_password" - StrCpy $R3 't "$R3"' + !insertmacro CALL_GETPARAM $R3 "password" "" "lbl_password" lbl_password: !insertmacro CALL_GETPARAM $R4 "interact" "0x10" "lbl_interact" StrCpy $6 0x10 IntCmp $R4 0 +2 @@ -224,21 +225,32 @@ lbl_path: !insertmacro CALL_GETPARAM $R7 "display" "$2" "lbl_display" lbl_display: - System::Call 'advapi32::CreateServiceA(i r4, t r2, t R7, i ${SERVICE_ALL_ACCESS}, \ - i R4, i R5, i 0, t R6, n, n, $R1, $R2, $R3) i.r6' + System::Call 'advapi32::CreateServiceW(i r4, w r2, w R7, i ${SERVICE_ALL_ACCESS}, \ + i R4, i R5, i 0, w R6, n, n, w R1, $R8, w R3) i.r6' + Pop $R8 Pop $R7 Pop $R6 Pop $R5 Pop $R4 Pop $R3 Pop $R2 Pop $R1 StrCmp $6 0 lbl_done lbl_good + ; set description + lbl_setdesc: + Push $R1 + System::Call '*(w r1) i.R1' + StrCpy $6 '1' + System::Call 'advapi32::ChangeServiceConfig2W(i r5, i 1, i $R1) i.r6' + System::Free $R1 + Pop $R1 + StrCmp $6 0 lbl_done lbl_good + ; delete service lbl_delete: System::Call 'advapi32::DeleteService(i r5) i.r6' StrCmp $6 0 lbl_done lbl_good
Usage Examples
- Stop a service whose name defined in macro
!insertmacro SERVICE stop "${SERVICE_NAME}" ""
- Create a service using macros for name; no newlines in the arguments
!insertmacro SERVICE create "${SERVICE_NAME}" "path=$INSTDIR\x-win32.exe;autostart=1;interact=0;display=${SERVICE_DISPLAYNAME};description=${SERVICE_DESCRIPTION};"
The code currently uses the t text type and a forced A function suffix, these don't match in the unicode build! All it takes is to remove the A suffix probably (And test that the code still works) --Anders 16:46, 5 August 2010 (UTC)
To whomever maintains this code.
There is an easy way to get rid of the following define lines:
!ifndef UN !define UN "" !endif
1) Just add another parameter (UN) to the SERVICE macro (line just below the above)...
CHANGE FROM:
!macro SERVICE ACTION NAME PARAM
TO:
!macro SERVICE ACTION NAME PARAM UN
This macro already uses the global value of the UN define; with the above change, it will use the local value.
2) Similarly, change the CALL_GETPARAM macro by also adding the (UN) parameter
CHANGE FROM:
!macro CALL_GETPARAM VAR NAME DEFAULT LABEL
TO:
!macro CALL_GETPARAM VAR NAME DEFAULT LABEL UN
3) Finally, change all the calls to the CALL_GETPARAM to add the (UN) parameter. In the code, all those calls are made from the FUNC_SERVICE macro and this one already has the (UN) parameter but doesn't make any use of it! There are 11 such calls in FUNC_SERVICE... So for example, change the following call:
CHANGE FROM:
!insertmacro CALL_GETPARAM $R1 "depend" "n" "lbl_depend"
TO:
!insertmacro CALL_GETPARAM $R1 "depend" "n" "lbl_depend" "${UN}"
What those changes buy you is the ability to call this code from your installer either in regular install or in uninstall code (I believe the global DEFINE only lets you call this code in one of those context)! For example, you can create and start a service in your install code using the following line:
!insertmacro SERVICE "create" <Service Name> "<params>" ""
!insertmacro SERVICE "start" <Service Name> "" ""
and you can stop and delete it in your uninstall code using the following line:
!insertmacro SERVICE "stop" <Service Name> "" "un."
!insertmacro SERVICE "delete" <Service Name> "" "un."
Error in lbl_description
The line
strcmp $R7 "error" 0 lbl_descriptioncomplete
after label lbl_description is incorrect. ChangeServiceConfig2 returns a boolean. Thus you have to change it to
strcmp $R7 0 0 lbl_descriptioncomplete
Claus Henning (195.226.184.202) 12:33, 6 January 2011 (UTC)
Added function: waitfor
I added a function to servicelib that waits for the service to reach a specific state. This function takes two parameters:
- status
- Can be running, stopped or paused and specifies for which state the function should wait.
- timeout
- Specifies the maximum time to wait (in seconds). It the timeout is reached before the service enters the desired state, "timeout" is returned in $0
lbl_waitfor: !insertmacro CALL_GETPARAM $7 "status" "n" "lbl_done" ; $7 is status as string StrCpy $8 ${SERVICE_RUNNING} ; $8 is status as hex int StrCmp $7 "running" lbl_waitforstatus StrCpy $8 ${SERVICE_STOPPED} StrCmp $7 "stopped" lbl_waitforstatus StrCpy $8 ${SERVICE_PAUSED} StrCmp $7 "paused" lbl_waitforstatus StrCpy $0 "false" ; illegal parameter "status" Goto lbl_done lbl_waitforstatus: !insertmacro CALL_GETPARAM $9 "timeout" "30" "lbl_waitfortimeout" ; $9 is timeout in seconds lbl_waitfortimeout: Push $R1 ; SERVICE_STATUS structure StrCpy $0 "timeout" ; in case we reach timeout lbl_waitforloop: Sleep 1000 System::Call '*(i,i,i,i,i,i,i) i.R1' System::Call 'advapi32::QueryServiceStatus(i r5, i $R1) i' System::Call '*$R1(i, i .r6)' ; $6 is now service status from QueryServiceStatus() System::Free $R1 IntOp $9 $9 - 1 StrCmp $9 0 lbl_done ; timeout reached IntFmt $6 "0x%X" $6 IntCmp $6 $8 0 lbl_waitforloop lbl_waitforloop Pop $R1 Goto lbl_good
I hope you find this useful, however it's up to you to add it to the 'official' library. I just wanted to contribute my work because your library has helped me a lot!
--Christifuzius 14:51, 10 January 2012 (UTC)