【问题标题】:NSIS Installer failed to start/stop serviceNSIS 安装程序无法启动/停止服务
【发布时间】:2015-10-22 01:48:56
【问题描述】:

我使用的是 WindowsXP、NSIS 2.46 和 nsSCM 插件,并且有 4 台机器具有几乎相同的环境(硬件 + 软件),因为它们来自相同的 GHOST 映像,但应用层的更改非常有限(没有更改任何系统设置)。

我正在使用 NSIS 安装程序将我的应用程序安装到他们,详细过程是:

  1. 停止“Apache2.2”服务。
  2. 将文件复制到 Apache 根文件夹。
  3. 创建快捷方式
    带脚本:
 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. 启动“Apache2.2”服务。

    带脚本:

  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}

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

现在问题出在第4步在其中两台机器上,总是弹出ERROR,总是需要手动启动服务(没有错误),但是同时,快捷方式创建成功。

我检查了系统日志、Apache 日志,但找不到错误日志/消息。

我花了一天时间尝试了所有方法,最后,我发现一旦我删除了第 3 步,一切都很好,所以知道为什么吗?

[编辑0]:

为了解决问题,我必须切换第 3 步和第 4 步,至少现在效果很好。

【问题讨论】:

  • CreateShortcut 应该与插件调用完全无关,我很确定还有其他事情发生。您使用的是 NSIS 3 beta 还是 NSIS 2.46?
  • @Anders 在我逐行注释掉脚本并看到结果之前,我也不敢相信。我正在使用 NSIS 2.46。
  • @Anders 有什么建议可以缩小范围吗?
  • @Shawn:你能尝试用原生 Windows 工具停止/启动服务吗?即网络命令。 !insertmacro ShellExecWait "open" "net" "stop ${_SERVICENAME}" "" SW_HIDE "";如果您需要 ShellExecute 宏,请告诉我。
  • @Shawn 我将尝试创建一些使用系统插件的代码,并在执行操作时打印错误代码,但可能需要一两天时间。如果可行,则可能是插件有问题。您是否尝试过 wiki 中的任何其他服务插件/宏? (nsis.sourceforge.net/How_do_I_start/stop/create/remove/…)

标签: windows installation nsis


【解决方案1】:

CreateShortcut 应该对插件没有影响,所以这很奇怪。如果我们可以将其缩小为 NSIS 中插件 API 的问题或插件本身的问题,那就太好了。或许你可以试试SimpleSC 插件?

这是一些使用系统插件手动完成的代码。它不漂亮,但如果失败应该显示相关的错误代码。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 2014-05-14
    • 2015-12-13
    相关资源
    最近更新 更多