2012-01-07 2 views
2

ExecDOS 플러그인을 사용하여 SQL 스크립트를 실행하는 명령 줄 도구를 호출하는 NSIS 설치 관리자가 있습니다. ExecDos는 비동기 모드에서 호출되며 명령 줄 도구가 완료 될 때까지 진행률 막대를 업데이트하고 IsDone 함수를 호출하는 식으로 반복합니다.NSIS ExecDos 플러그인 - IsDone 기능은 일부 컴퓨터에서는 작동하지만 다른 제품에서는 작동하지 않습니다.

내가 겪고있는 문제는 IsDone 검사가 프로세스가 실제로 실행 중일 때 잘못보고되어 설치 프로그램이 완료된 후 백그라운드에서 계속 진행된다는 것입니다. 나는 그것이 작동하지 않는 컴퓨터들 사이에 공통점을 찾을 수 없기 때문에 누군가가 아이디어를 갖고 있거나 코드에서 오류를 발견 할 수 있기를 바라고 있습니다.

Function UpdateDatabase 
    !insertmacro SetBannerText "Updating database" 0 0   
    !insertmacro Log "About to update the database" 

    StrCpy $UpdateDatabase_PreviousScriptNumber 0  

    SetShellVarContext all   

    Push "ExecDos::End" # Add a marker for the loop to test for. 
    ExecDos::exec /NOUNLOAD /ASYNC '"$ComSpec" /S /C ""$INSTDIR\Database\Tool\DatabaseResetTool.Console.exe" -sp="$INSTDIR\Database\Scripts" -cs="Data Source=$DatabaseServer;Initial Catalog=$Database;User ID=sa;Password=*********;Persist Security Info=true;MultipleActiveResultSets=True;Language=English" -eoe"' '' '$APPDATA\Company\$ApplicationPrefix\Database Update.log' 
    Pop $DatabaseUpdate_ProcessHandle  
Loop:  
    ExecDos::isdone /NOUNLOAD $DatabaseUpdate_ProcessHandle 
    Pop $DatabaseUpdate_Done  

    StrCpy $0 "$APPDATA\Company\$ApplicationPrefix\Database Update.log" 
    StrCpy $1 "$TEMP\Database Update.log" 
    StrCpy $2 0 
    System::Call 'kernel32::CopyFile(t r0, t r1, b r2) ?e' 

    ${LineRead} "$TEMP\Database Update.log" "-2" $DatabaseUpdate_LogFileLine 

    ${StrTok} $DatabaseUpdate_LogFileLineEndPart $DatabaseUpdate_LogFileLine "(" "L" "1"  
    ${StrTok} $DatabaseUpdate_ScriptNumber $DatabaseUpdate_LogFileLineEndPart "/" "0" "1"  
    ${StrTok} $DatabaseUpdate_ScriptCountUnprocessed $DatabaseUpdate_LogFileLineEndPart "/" "1" "1"  
    ${StrTok} $DatabaseUpdate_ScriptCount $DatabaseUpdate_ScriptCountUnprocessed ")" "0" "1" 

    ${If} $DatabaseUpdate_ScriptNumber != "" 
    ${AndIf} $DatabaseUpdate_ScriptCount != ""   
    FloatOp::D $DatabaseUpdate_ScriptNumber $DatabaseUpdate_ScriptCount   
    FloatOp::M $0 100       

    ${If} $UpdateDatabase_PreviousScriptNumber != $DatabaseUpdate_ScriptNumber            
     !insertmacro SetBannerText "Updating database$\r$\n$\r$\nRunning script $DatabaseUpdate_ScriptNumber of $DatabaseUpdate_ScriptCount" 0 $0 
     StrCpy $UpdateDatabase_PreviousScriptNumber $DatabaseUpdate_ScriptNumber 
    ${EndIf}            
    ${EndIf}  

    Sleep 200 

    StrCmp $DatabaseUpdate_Done "0" Loop Done 
Done: 
    Push "$TEMP\Database Update.log" 
    Push "exception" 
    Call FileSearch 
    Pop $0 
    Pop $1  

    ${If} $0 != "0" 
    StrCpy $InstallError 1 
    !insertmacro LogError "Database update failed. Please review the 'Database Update.log' to see the detail error message" ""   
    ${EndIf}  
FunctionEnd 
+0

루프가 깨지면 $ DatabaseUpdate_Done 1 또는 -1이 발생합니까? – Anders

답변

3
나는 정확한 문제가 무엇인지 모르지만 당신은 아마 수정해야 스크립트와 다른 문제가

:

  • System::Call 'kernel32::CopyFile(t r0, t r1, b r2) ?e'b이 유효한 시스템 플러그인 유형이 아닌, i를 사용 . ?e이 스택을 푸시하면이 값을 팝업하지 않으므로 복사가 성공했는지 확인하지 않습니다. 재 믹스에 cmd.exe를 데려없이 작동하므로 System::Call 'kernel32::CopyFile(t r0, t r1, i 0)i.r0'로 교체하고 당신은 $ COMSPEC 내가 cmd.exe를 인용 문제를 처리하는 것입니다 가정 ""를 사용하는 ${If} $0 = 0 ...deal with error

  • 확인, ExecDos 파이프를 사용합니다.

  • 당신은 팝업 결코 시험 일부 다른 것들 Push "ExecDos::End"

에 대한 귀하의 스크래치 공간으로 $ Pluginsdir를 사용, 단지 ExecDos::exec /NOUNLOAD /ASYNC '"$INSTDIR\Da...

  • 당신은 정말 $ 온도에있는 모든 파일을 제어하지 않는 실행 시도 당신은 조사하고 싶을지도 모르다 :

    • SetShellVarContext all는 일반적인 appdata/programdata에 이렇게시킨다 당신은 관리자 야.
    • 더 긴 수면을 시도 ...
    • 는 팝업 결코 ?e 값이 함수가 잘못된 매개 변수로 끝나는 있도록의 isDone 매개 변수는 스택에 푸시하지 않도록 스택을 충전 끝 가능성이 있습니까?

  • 이 당신이 System::Call 'kernel32::WaitForSingleObject(i $DatabaseUpdate_ProcessHandle ,i 0)i.r0'와의 isDone과 return values listed on MSDN에 $ 0의 값을 비교하는 전화를 대체 할 수 있어야 디버깅합니다.

    +1

    내 코드에 대한 자세한 조사를 해주셔서 대단히 감사합니다. 나는 앞으로 며칠 동안 당신이 제안한 변화를 구현할 것이며, 그들 중 하나가 내가 가진 특정 문제를 해결할 수 있기를 바랍니다. –

    +0

    나는 당신의 모든 제안을 구현했으며 문제는 고쳐진 것처럼 보입니다. 다시 한번 감사드립니다. 불행히도 시간 압박은 개별적으로 각 변경 사항을 테스트 할 수 없으므로 어느 것이 문제의 근원인지 알 수 없었습니다. –

    관련 문제