1
votes

Hello I have problem with NSIS uninstaller.

I instaled software and create a service. Service name is named by user( for example troll)

Soo I have service troll it is running and working everything is all right.

If I want uninstall software I must remove this service; I've tried several way with plugins simpleSC and nsSCM, nothing helped me.

If I wrote for ex:

  • nsSCM::Remove "troll" service is removed
  • but when I write nsSCM::Remove "$0" ->nothing happen

Where is my mistake? In getting service name from stack? I don't know the name of the service since it is custom any help will be helpfull :D

2
How do you get the installed service name? Show the code, the problem might be on this other side. - Seki
I testing it on tomcat service,I intalled servicein that way: ` nsExec::ExecToLog '"$INSTDIR\TamasAppServer\bin\tomcat7.exe" //IS//tomcat7` + other info about description,logPath,JVM ...etc - exofus
Do you store the name after installation? How do you read back that name? - Seki
by pop$0 when I do DetailPrint "$0" it shows service name so I thing it is ok - exofus
AND yes I tried uninstall service by //DS - exofus

2 Answers

0
votes

The contents of variables in the installer are not automatically restored in the uninstaller. You must write the service name in the registry or a .INI file in the installer and then read this value in the uninstaller.

0
votes

I don't have any reputation, otherwise this would have been in a comment. Anyway, you say the services' name is "named by user"

Are you saying the end-user designates the service name or is it simply the end-user's username?

If it's the latter you could use this without any plugins, excluding ExecDos:

Var User

!define SVC `$User`
!define SC  `$SYSDIR\sc.exe`

System::Call "advapi32::GetUserName(t.r0,*i${NSIS_MAX_STRLEN})i" 
StrCpy $User $0
ClearErrors
ExecDos::Exec /TOSTACK `"${SC}" stop "${SVC}"`
Sleep 50
ExecDos::Exec /TOSTACK `"${SC}" delete "${SVC}"`

If it's the first option then you'll need to do something like this in your installer whenever the user specifies the service's name. Hope this isn't too complicated.

;= VARIABLES 
;= ################
Var Bit
Var UserService

;= DEFINES
;= ################
!define SVC         `$UserService`
!define SCKEY       SYSTEM\CurrentControlSet\services\${SVC}
!define HKLM        HKLM\${SCKEY}
!define SC          `$SYSDIR\sc.exe`
!define GETCURRPROC `kernel32::GetCurrentProcess()i.s`
!define WOW         `kernel32::IsWow64Process(is,*i.r0)`

;= MACROS
;= ################
;=#
;= Service::Example
; ${Service::CMD} "ServiceName" /DISABLEFSR $0 $1
;       ::CMD       = Either QueryConfig, Stop, or Remove. 
;       ServiceName = The service name to be handled
;       /DISABLEFSR = Disables file-system redirection if running on x64. Use "" to skip.
;       $0          = Return after call
;       $1          =  ''     ''    ''
!define Service::QueryConfig `!insertmacro _Service::QueryConfig`
!macro _Service::QueryConfig _SVC _FSR _ERR1 _ERR2
    ReadEnvStr $R0 COMSPEC
    StrCmpS $Bit 64 0 +4
    StrCmp "${_FSR}" /DISABLEFSR 0 +3
    ExecDos::Exec /TOSTACK /DISABLEFSR `"$R0" /c "${SC} qc "${_SVC}" | FIND "BINARY_PATH_NAME""`
    Goto +2
    ExecDos::Exec /TOSTACK `"$R0" /c "${SC} qc "${_SVC}" | FIND "BINARY_PATH_NAME""`
    Pop ${_ERR1}
    Pop ${_ERR2}
    StrCmpS ${_ERR1} 0 0 +4
    StrCpy $R1 ${_ERR2} "" 29
    WriteINIStr "$EXEDIR\InstallData.ini" "Service" Path "$R1"
    ReadRegStr $R1 HKLM `${SVCKEY}` ImagePath
    WriteINIStr "$EXEDIR\InstallData.ini" "Service" Path "$R1"
    WriteINIStr "$EXEDIR\InstallData.ini" "Service" Name "${_SVC}"
!macroend
!define Service::Stop `!insertmacro _Service::Stop`
!macro _Service::Stop _SVC _FSR _ERR1 _ERR2
    StrCmpS $Bit 64 0 +4
    StrCmp "${_FSR}" /DISABLEFSR 0 +3
    ExecDos::Exec /TOSTACK /DISABLEFSR `"${SC}" stop "${_SVC}"`
    Goto +2
    ExecDos::Exec /TOSTACK `"${SC}" stop "${_SVC}"`
    Pop ${_ERR1}
    Pop ${_ERR2}
!macroend
!define Service::Remove `!insertmacro _Service::Remove`
!macro _Service::Remove _SVC _FSR _ERR1 _ERR2
    StrCmpS $Bit 64 0 +4
    StrCmp "${_FSR}" /DISABLEFSR 0 +3
    ExecDos::Exec /TOSTACK /DISABLEFSR `"${SC}" delete "${_SVC}"`
    Goto +2
    ExecDos::Exec /TOSTACK `"${SC}" delete "${_SVC}"`
    Pop ${_ERR1}
    Pop ${_ERR2}
!macroend

Function ".onInit" 
    System::Call `${GETCURRPROC}`
    System::Call `${WOW}`
    StrCmpS $0 0 +3
    StrCpy $Bit 64
    Goto +2
    StrCpy $Bit 32
FunctionEnd 

;=#
;= I don't know the code you're using but let's assume 
;= after the end-user specifies the service's name you
;= copy the name to the variable $UserService. This is
;= somewhere in the install process.


StrCpy $UserService $0
;#=#
;# This will write to an INI file | $EXEDIR\InstallData.ini
;#      [Service]
;#      Path=X:\Path\to\service\exe
;#      Name=ServiceName 
;#=#
${Service::QueryConfig} ${SVC} /DISABLEFSR $0 $1

;=#
;= Then in your uninstaller you could simply implement
;= this into your code for easy removal. I usually use
;= this method in my projects and it works pretty good
;= without the need for any extra plugins. 
ReadINIStr $0 "$EXEDIR\InstallData.ini" "Service" Name
${Service::Stop} "$0" /DISABLEFSR $0 $1
Sleep 50
${Service::Remove} "$0" /DISABLEFSR $0 $1

The /DISABLEFSR parameter should only be used on x64 machines. However, if you mess up there's a failsafe in the macros that will dodge this bullet for you. Boy, that was a lot, huh? And to my luck this will help you by no means. Lol. Hope this helps someone though.