简体   繁体   English

NSIS安装程序无法启动/停止服务

[英]NSIS Installer failed to start/stop service

I'm using WindowsXP, NSIS 2.46 with nsSCM plug-in, and have 4 machines with nearly the same environment(hardware + software) since they come from a same GHOST image but with very limited changes on application layer(no any system settings changed). 我使用的是WindowsXP,NSIS 2.46和nsSCM插件,并且具有4台几乎具有相同环境(硬件和软件)的计算机,因为它们来自同一GHOST映像,但是应用程序层的更改非常有限(未更改任何系统设置) )。

I'm using NSIS installer to install my application to them, detail process are: 我正在使用NSIS安装程序将应用程序安装到它们,详细过程为:

  1. Stop 'Apache2.2' service. 停止“ Apache2.2”服务。
  2. Copy files to Apache root folder. 将文件复制到Apache根文件夹。
  3. CreateShortCut CreateShortCut
    With script: 使用脚本:
  CreateShortCut "$SMPROGRAMS\\MyApp\\Stop.lnk" "$SYSDIR\\sc.exe" "stop MyAppService" "C:\\WINDOWS\\system32\\SHELL32.dll" 27 SW_SHOWMINIMIZED CreateShortCut "$SMPROGRAMS\\MyApp\\ShowDemo.lnk" "$PROGRAMFILES\\MyAppPath\\MyAppShowDemoHelper.exe" "-b 102" "C:\\WINDOWS\\system32\\SHELL32.dll" 24 SW_SHOWMINIMIZED 
  1. Start 'Apache2.2' service. 启动“ Apache2.2”服务。

    With script: 使用脚本:

  nsSCM::Start /NOUNLOAD "Apache2.2" Pop $0 ; return error/success ${If} $0 == "success" MessageBox MB_ICONINFORMATION|MB_OK "Successfully started 'Apache2.2' service" ${Else} MessageBox MB_ICONSTOP|MB_OK "Failed to start 'Apache2.2' service with result: $0, Contact help desk or start it manually!" ${EndIf} 

=========================== ==========================

Now the problem is the step 4 , in two of those machines , it always popup ERROR and always need manually to start the service(with no error), but meantime, the shortcuts are created successfully. 现在问题出在第4步中在其中两台计算机中 ,它总是弹出错误并始终需要手动启动服务(没有错误),但是与此同时,快捷方式已成功创建。

I've checked system logs, Apache logs, but no error logs/message could be found. 我已经检查了系统日志,Apache日志,但是找不到错误日志/消息。

I spend one day and tried everything, at last, I found once I remove the Step 3, everything is fine, so any idea Why? 我花了一天时间并尝试了所有步骤,最后,我发现删除步骤3后,一切都很好,所以知道为什么吗?

[Edit0]: [Edit0]:

For work around, I have to switch Step 3 and 4, at least now it works good. 要变通,我必须切换第3步和第4步,至少现在它运行良好。

CreateShortcut should have no impact on plugins so this is rather strange. CreateShortcut对插件应该没有影响,所以这很奇怪。 It would be nice if we could narrow this down to a problem with the plugin API in NSIS or a problem in the plugin itself. 如果我们可以将范围缩小到NSIS中的插件API问题或插件本身的问题,那将是很好的。 Maybe you could try the SimpleSC plugin? 也许您可以尝试SimpleSC插件?

Here is some code that does it manually with the system plugin. 这是一些使用系统插件手动执行的代码。 It is not pretty but should display a relevant error code if it fails. 它不是很漂亮,但是如果失败,则应显示相关的错误代码。

Section
!define MyServiceName "Spooler" ;"stisvc" 
ExecWait '"$SysDir\cmd.exe" /c net stop "${MyServiceName}"' ; Hack to make sure the service is stopped so we can try starting it again
Sleep 1111

InitPluginsDir
CreateShortcut "$PluginsDir\Test1.lnk" "$ExePath" ; Create some dummy shortcuts to possibly trigger the bug
CreateShortcut "$PluginsDir\Test2.lnk" "$ExePath"

!include LogicLib.nsh
!include Util.nsh
!define ERROR_SERVICE_ALREADY_RUNNING 1056
!define SC_MANAGER_CONNECT 0x0001
!define SERVICE_QUERY_STATUS 0x0004
!define SERVICE_START 0x0010
!define SERVICE_PAUSE_CONTINUE 0x0040
!define SERVICE_CONTROL_CONTINUE 3
!define SERVICE_STOPPED 1
!define SERVICE_START_PENDING 2
!define SERVICE_STOP_PENDING 3
!define SERVICE_RUNNING 4
!define SERVICE_CONTINUE_PENDING 5
!define SERVICE_PAUSE_PENDING 6
!define SERVICE_PAUSED 7

!macro WaitForServiceRunningStatus_
System::Store S
Pop $6
Pop $1
System::Call KERNEL32::GetTickCount()i.r7
System::Call '*(i,i,i,i,i,i,i)i.r2'
loop:
    System::Call 'ADVAPI32::QueryServiceStatus(ir1, ir2)i.r3'
    System::Call '*$2(i,i.r4)'
    ${If} $3 <> 0
        ${If} $4 = ${SERVICE_RUNNING}
            DetailPrint 'Service is now running.'
        ${Else}
            Sleep 250
            System::Call KERNEL32::GetTickCount()i.r8
            ${IfThen} $8 < $7 ${|} StrCpy $7 $8 ${|} ; Reset on GetTickCount rollover
            IntOp $8 $8 - $7
            IntCmpU $8 $6 "" loop
            DetailPrint 'Timeout! Service status is $4'
        ${EndIf}
    ${EndIf}
System::Free $2
System::Store L
!macroend
!macro WaitForServiceRunningStatus hSC MsTimeout
Push ${hSC}
Push ${MsTimeout}
${CallArtificialFunction} WaitForServiceRunningStatus_
!macroend

System::Call 'ADVAPI32::OpenSCManager(t"", i0, i${SC_MANAGER_CONNECT})i.r0 ?e'
Pop $9
${If} $0 = 0
    DetailPrint 'OpenSCManager(t"", i0, i${SC_MANAGER_CONNECT}) failed with error $9'
${Else}
    System::Call 'ADVAPI32::OpenService(ir0, t"${MyServiceName}", i${SERVICE_QUERY_STATUS}|${SERVICE_START}|${SERVICE_PAUSE_CONTINUE})i.r1 ?e'
    Pop $9
    ${If} $1 = 0
        DetailPrint 'OpenService("${MyServiceName}") failed with error $9'
    ${Else}
        System::Call '*(i,i,i,i,i,i,i)i.r2'
        System::Call 'ADVAPI32::QueryServiceStatus(ir1, ir2)i.r3 ?e'
        Pop $9
        ${If} $3 = 0
            DetailPrint 'QueryServiceStatus failed with error $9'
            StrCpy $4 0 ; We failed, set to unused code so we stop processing
        ${Else}
            System::Call '*$2(i.r3,i.r4,i.r5,i,i,i,i)'
            IntFmt $3 "%#x" $3
            IntFmt $4 "%#x" $4
            IntFmt $5 "%#x" $5
            DetailPrint 'QueryServiceStatus: Type=$3, CurrentState=$4 ControlsAccepted=$5'
        ${EndIf}
        ${If} $4 = ${SERVICE_PAUSE_PENDING}
        ${OrIf} $4 = ${SERVICE_PAUSED}
            System::Call 'ADVAPI32::ControlService(ir1, i${SERVICE_CONTROL_CONTINUE}, ir2)i.r3 ?e'
            Pop $9
            ${If} $3 = 0
                DetailPrint 'ControlService(SERVICE_CONTROL_CONTINUE) failed with error $9'
            ${Else}
                DetailPrint 'Resuming "${MyServiceName}"...'
                !insertmacro WaitForServiceRunningStatus $1 5000
            ${EndIf}
        ${ElseIf} $4 = ${SERVICE_CONTINUE_PENDING}
            !insertmacro WaitForServiceRunningStatus $1 5000
        ${ElseIf} $4 >= ${SERVICE_STOPPED}
            ${If} $4 = ${SERVICE_RUNNING}
                DetailPrint "Service already running"
            ${Else}
                System::Call 'ADVAPI32::StartService(ir1, i0, i0)i.r3 ?e'
                Pop $9
                ${If} $3 = 0
                    DetailPrint 'StartService failed with error $9'
                ${Else}
                    DetailPrint 'Starting "${MyServiceName}"...'
                    !insertmacro WaitForServiceRunningStatus $1 9000
                ${EndIf}
            ${EndIf}
        ${EndIf}
        System::Free $2
        System::Call 'ADVAPI32::CloseServiceHandle(i.r1)'
    ${EndIf}
    System::Call 'ADVAPI32::CloseServiceHandle(i.r0)'
${EndIf}
SectionEnd

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM