Find and Close or Terminate: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
mNo edit summary
No edit summary
Line 5: Line 5:
'''Requires:''' [[System plug-in|System]] plug-in.
'''Requires:''' [[System plug-in|System]] plug-in.


This macro can find process by it's main window class or title (or title part), try to close it and terminate if process is still alive. Decorated as 'macro' (not function) because this may be usefull both with installer and uninstaller.
This macro can find process by it's main window class or title, try to close it and terminate if process is still alive. Decorated as 'macro' (not function) because this may be usefull both with installer and uninstaller.


Sample below finds window by it's class, sends WM_CLOSE message and waits "timeout" for process exit. If process is still running after this, script asks user's confirmation (optional, comment MessageBox line to skip) and terminates process. Then repeats with all windows of this 'class'.  
Sample below finds window by it's class, sends WM_CLOSE message and waits "timeout" for process exit. If process is still running after this, script asks user's confirmation (optional, comment MessageBox line to skip) and terminates process.  
<highlight-nsis>
<highlight-nsis>
!define APP_NAME find_close_terminate
!define APP_NAME find_close_terminate
!define WND_CLASS "Outlook Express Browser Class"
!define WND_CLASS "Outlook Express Browser Class"
Line 21: Line 22:




LangString termMsg ${LANG_ENGLISH} "Installer cannot stop running ${WND_TITLE}.$\nClick OK to terminate application."
LangString termMsg ${LANG_ENGLISH} "Installer cannot stop running ${WND_TITLE}.$\nDo you want to terminate process?"
LangString stopMsg ${LANG_ENGLISH} "Stopping ${WND_TITLE} Application"
LangString stopMsg ${LANG_ENGLISH} "Stopping ${WND_TITLE} Application"


Line 30: Line 31:
     Push $2 ; process handle
     Push $2 ; process handle
     DetailPrint "$(stopMsg)"
     DetailPrint "$(stopMsg)"
  loop:
     FindWindow $0 '${WND_CLASS}' ''
     FindWindow $0 '${WND_CLASS}' '' 0 $0
     IntCmp $0 0 done
     IntCmp $0 0 done
;    System::Call 'user32.dll::GetWindowText(i r0, t .r1, i 1024) i .r2'
;    System::Call 'shell32.dll::StrStr(t r1, t ${WND_TITLE}) i .r2'
;    IntCmp $2 0 +1 loop
     System::Call 'user32.dll::GetWindowThreadProcessId(i r0, *i .r1) i .r2'
     System::Call 'user32.dll::GetWindowThreadProcessId(i r0, *i .r1) i .r2'
     System::Call 'kernel32.dll::OpenProcess(i ${SYNC_TERM}, i 0, i r1) i .r2'
     System::Call 'kernel32.dll::OpenProcess(i ${SYNC_TERM}, i 0, i r1) i .r2'
Line 41: Line 38:
     System::Call 'kernel32.dll::WaitForSingleObject(i r2, i ${TO_MS}) i .r1'
     System::Call 'kernel32.dll::WaitForSingleObject(i r2, i ${TO_MS}) i .r1'
     IntCmp $1 0 close
     IntCmp $1 0 close
     MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "$(termMsg)" /SD IDOK IDOK terminate
     MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION "$(termMsg)" /SD IDYES IDYES terminate IDNO close
     System::Call 'kernel32.dll::CloseHandle(i r2) i .r1'
     System::Call 'kernel32.dll::CloseHandle(i r2) i .r1'
     Quit
     Quit
Line 48: Line 45:
   close:
   close:
     System::Call 'kernel32.dll::CloseHandle(i r2) i .r1'
     System::Call 'kernel32.dll::CloseHandle(i r2) i .r1'
    Goto loop
   done:
   done:
     Pop $2
     Pop $2
Line 63: Line 59:
SectionEnd
SectionEnd
</highlight-nsis>
</highlight-nsis>
To find window by it's fixed text title (caption) instead of window class or both by class and title, replace FindWindow line in the macro above with one of the following lines:
To find window by it's title (caption) instead of window class or both by class and title, replace FindWindow line in the macro above with one of the following lines:
<highlight-nsis>
<highlight-nsis>
     FindWindow $0 '' '${WND_TITLE}' 0 $0
     FindWindow $0 '' '${WND_TITLE}'
     FindWindow $0 '${WND_CLASS}' '${WND_TITLE}' 0 $0
     FindWindow $0 '${WND_CLASS}' '${WND_TITLE}'
</highlight-nsis>
To find window by part of it's title (like "WinZip" in the "WinZip - Sample.zip" title) uncomment 3 lines in the code above (GetWindowText, StrStr and IntCmp). To check all top level windows with WND_TITLE in the title (with any window class), remove class parameter in the FindWIndow line
<highlight-nsis>
    FindWindow $0 '' '' 0 $0
</highlight-nsis>
</highlight-nsis>


[[Category:Other Products Handling Functions]]
[[Category:Other Products Handling Functions]]

Revision as of 12:04, 20 November 2005

Author: Takhir (talk, contrib)


Description

Requires: System plug-in.

This macro can find process by it's main window class or title, try to close it and terminate if process is still alive. Decorated as 'macro' (not function) because this may be usefull both with installer and uninstaller.

Sample below finds window by it's class, sends WM_CLOSE message and waits "timeout" for process exit. If process is still running after this, script asks user's confirmation (optional, comment MessageBox line to skip) and terminates process.

!define APP_NAME find_close_terminate
!define WND_CLASS "Outlook Express Browser Class"
!define WND_TITLE "Outlook Express"
!define TO_MS 2000
!define SYNC_TERM 0x00100001
 
!include WinMessages.nsh
 
Name "${APP_NAME}"
OutFile "${APP_NAME}.exe"
 
 
LangString termMsg ${LANG_ENGLISH} "Installer cannot stop running ${WND_TITLE}.$\nDo you want to terminate process?"
LangString stopMsg ${LANG_ENGLISH} "Stopping ${WND_TITLE} Application"
 
!macro TerminateApp
 
    Push $0 ; window handle
    Push $1
    Push $2 ; process handle
    DetailPrint "$(stopMsg)"
    FindWindow $0 '${WND_CLASS}' ''
    IntCmp $0 0 done
    System::Call 'user32.dll::GetWindowThreadProcessId(i r0, *i .r1) i .r2'
    System::Call 'kernel32.dll::OpenProcess(i ${SYNC_TERM}, i 0, i r1) i .r2'
    SendMessage $0 ${WM_CLOSE} 0 0 /TIMEOUT=${TO_MS}
    System::Call 'kernel32.dll::WaitForSingleObject(i r2, i ${TO_MS}) i .r1'
    IntCmp $1 0 close
    MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION "$(termMsg)" /SD IDYES IDYES terminate IDNO close
    System::Call 'kernel32.dll::CloseHandle(i r2) i .r1'
    Quit
  terminate:
    System::Call 'kernel32.dll::TerminateProcess(i r2, i 0) i .r1'
  close:
    System::Call 'kernel32.dll::CloseHandle(i r2) i .r1'
  done:
    Pop $2
    Pop $1
    Pop $0
 
!macroend
 
 
Section "Dummy Section" SecDummy
 
!insertmacro TerminateApp
 
SectionEnd

To find window by it's title (caption) instead of window class or both by class and title, replace FindWindow line in the macro above with one of the following lines:

    FindWindow $0 '' '${WND_TITLE}'
    FindWindow $0 '${WND_CLASS}' '${WND_TITLE}'