- NSIS Discussion
- Set focus to installer window
Archive: Set focus to installer window
kobus
21st July 2004 11:12 UTC
Set focus to installer window
Hi,
I'am trying to prevent user to run installer more then once at a time. (it works) :)
In such a case I want to display message about it and set focus to already working installer winodw.
my code:
Function .onInit
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutexS") i .r1 ?e'
Pop $R0
StrCmp $R0 0 ok
MessageBox MB_OK|MB_ICONSTOP "Installer already working"
FindWindow $1 "" "${PRODUCT_NAME}" 0 0
SendMessage $1 0x00007 0 0 'send WM_SETFOCUS
Abort
ok:
...
FunctionEnd
why it didn't work ? Any idea ?
with WM_CLOSE (0x00010) it works perfectly ...
thanks in advance
kobus
deguix
21st July 2004 11:58 UTC
You're calling it in .onInit, at this time the installer GUI wasn't loaded so it will never find a window and set focus to it. Use .onGUIInit instead.
kobus
21st July 2004 12:04 UTC
Originally posted by deguix
You're calling it in .onInit, at this time the installer GUI wasn't loaded so it will never find a window and set focus to it. Use .onGUIInit instead.
The scenario is different.
User run installer (instance no 1). Then run installer agian (instance no 2).
And now instance no 2. should inform user that installer is already working, set focus to window with instance no 1 and close itself (instance no 2).
anyway ... with .onGuiInit didn't work too. :(
kobus
iceman_k
21st July 2004 14:25 UTC
Interesting. The code seems to be good. Can you upload your script?
[edit]
OK, this works:
Function .onInit
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutexS") i .r1 ?e'
Pop $R0
StrCmp $R0 0 ok
MessageBox MB_OK|MB_ICONSTOP "Installer already working"
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup" 0 0
System::call "user32::SetWindowPos(i r1, i -1, i 0, i 0, i 0, i 0, i 0x02|0x01) i.r1"
Pop $1
Abort
ok:
...
FunctionEnd
When you issue the FindWindow instruction, make sure to specify the installer name followed by " Setup". In my case the installer name was "${PRODUCT_NAME} ${PRODUCT_VERSION}"
[/edit]
kobus
22nd July 2004 07:20 UTC
When you issue the FindWindow instruction, make sure to specify the installer name followed by " Setup". In my case the installer name was "${PRODUCT_NAME} ${PRODUCT_VERSION}"
I set title with caption for "${PRODUCT NAME}" so when I am trying to find window I use "${PRODUCT NAME}" as a title without "setup" word and it works ! - WM_CLOSE message close desired window. Only WM_SETFOCUS didn't work ...
I attach the code (sorry the UI is in Polish ...)
The problematic code is in onInit funcion
thanks for spending time with my problems
kobus
iceman_k
22nd July 2004 13:04 UTC
Your attachment is missing.
Anyway, did you try SetWindowPos as in my example:
System::call "user32::SetWindowPos(i r1, i -1, i 0, i 0, i 0, i 0, i 0x02|0x01) i.r1"
Pop $1
This seems to work.
kobus
22nd July 2004 13:29 UTC
Yes, it's really works !!! :up:
That's was my typo error :(
thanks a lot
kobus
externe
17th November 2004 00:12 UTC
Hello,
I just saw this post and test the code above. But it won't work for me.
I rewrite it here.
!define PRODUCT_NAME "My application"
!define PRODUCT_VERSION "1.0"
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
outfile "test.exe"
Function .onInit
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutexS") i .r1 ?e'
Pop $R0
StrCmp $R0 0 ok
MessageBox MB_OK|MB_ICONSTOP "Installer already working"
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup"
System::call "user32::SetWindowPos(i r1, i -1, i 0, i 0, i 0, i 0, i 0x02|0x01) i.r1"
Pop $1
Abort
ok:
FunctionEnd
section "Install"
sectionend
Can someone see why that doesn't work ?
Thanks :)
Afrow UK
17th November 2004 14:44 UTC
I found that it won't work for that example because once the installation has completed, the window title will become:
${PRODUCT_NAME} ${PRODUCT_VERSION} Setup: Completed
If you change it to that (in FindWindow) then it works fine. This will be a problem though because the title is never going to be the same.
-Stu
Comm@nder21
17th November 2004 14:48 UTC
why didn't you try the usual way?
FindWindow $1 "#32770"
should work for every title ...
Afrow UK
17th November 2004 15:32 UTC
Doesn't work :p
-Stu
Takhir
17th November 2004 18:23 UTC
Originally posted by externe
Can someone see why that doesn't work ?
Tested on Win98, NSIS 2.01 - works fine.
BTW in one of my apps customer asked do not show second "already running" message box, but close 3-rd instance silently :(
#32770 window class - few and not installer dialog windows may present on the desktop :)
externe
17th November 2004 19:02 UTC
Hey thanks, I never seen that the titlebar name changed...
Now it work ( code below )
But the focus are not really doing. (The window is gray)
Is it normal ?
Thanks
:)
!define PRODUCT_NAME "My application"
!define PRODUCT_VERSION "1.0"
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
outfile "test.exe"
Function .onInit
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutexS") i .r1 ?e'
Pop $R0
StrCmp $R0 0 ok
MessageBox MB_OK|MB_ICONSTOP "Installer already working"
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup"
System::call "user32::SetWindowPos(i r1, i -1, i 0, i 0, i 0, i 0, i 0x02|0x01) i.r1"
Pop $1
Abort
ok:
FunctionEnd
section "Install"
MessageBox MB_OK|MB_ICONSTOP "I'm running... Launch another instance for testing... "
sectionend
Afrow UK
17th November 2004 20:05 UTC
It won't be working because the title will be "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup: Installing Files" and so on.
I'm going to have to modify that script...
-Stu
Afrow UK
17th November 2004 20:09 UTC
!define PRODUCT_NAME "My application"
!define PRODUCT_VERSION "1.0"
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
outfile "test.exe"
Function .onInit
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutexS") i .r1 ?e'
Pop $R0
StrCmp $R0 0 ok
MessageBox MB_OK|MB_ICONSTOP "Installer already working"
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup"
StrCmp $1 0 0 setFocus
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup: License Agreement"
StrCmp $1 0 0 setFocus
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup: Installation Options"
StrCmp $1 0 0 setFocus
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup: Directory"
StrCmp $1 0 0 setFocus
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup: Installing Files"
StrCmp $1 0 0 setFocus
FindWindow $1 "" "${PRODUCT_NAME} ${PRODUCT_VERSION} Setup: Completed"
setFocus:
System::call "user32::SetWindowPos(i r1, i -1, i 0, i 0, i 0, i 0, i 0x02|0x01) i.r1"
Pop $1
Abort
ok:
FunctionEnd
Section "Install"
...
SectionEnd
This should work (might want to try it).
-Stu
externe
18th November 2004 07:25 UTC
Nice, Thanks Afrow UK. :)
I understand the way well now :p
Is it possible to list the windows ? I mean create a macro who's loop in the list of all window and search the words "${PRODUCT_NAME}" and "Setup".
Nice idea no ?
Bye.
Takhir
18th November 2004 07:45 UTC
Program can check all top level dialog windows - this should work with custom installer pages too.
Function .onInit
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutexS") i .r1 ?e'
Pop $R0
StrCmp $R0 0 ok
MessageBox MB_OK|MB_ICONSTOP "Installer already working"
StrLen $5 "${PRODUCT_NAME} ${PRODUCT_VERSION}"
loop:
FindWindow $0 '#32770' '' 0 $0
IntCmp $0 0 ok
StrCpy $3 ${NSIS_MAX_STRLEN}
System::Call "user32.dll::GetWindowText(i r0, t r1, i r3) i.r4"
StrCpy $6 $1 $5
StrCmp $6 "${PRODUCT_NAME} ${PRODUCT_VERSION}" 0 loop
System::call "user32::SetWindowPos(i r1, i -1, i 0, i 0, i 0, i 0, i 0x02|0x01) i.r1"
Pop $1
Abort
ok:
FunctionEnd
externe
18th November 2004 10:37 UTC
Well, sorry if i'm a few OT, but I want to understand what return exactly :
FindWindow $0 '#32770' '' 0 $0
So I write this little test : A 10 loop wich open a messagebox with the return of FindWindow.
outfile "test.exe"
Section "Install"
StrCpy $9 0
loop:
FindWindow $0 '#32770' '' 0 $0
MessageBox MB_OK|MB_ICONSTOP $0
IntOp $9 $9 + 1
StrCmp $9 10 0 loop
SectionEnd
And that give me numbers : 918078, 66148, 66188, 1180982, 0, ...
Can someone tell me what mean those numbers ?
Thanks :)
Takhir
18th November 2004 11:48 UTC
This means that you have 4 dialog type windows (class #32770) on the desktop, and numbers are system window handles. Using handle program can read window caption (this case).
externe
18th November 2004 12:39 UTC
Ok,
#32770 mean USER dialog boxes thanks!
I found info also here : MSDN
You say : "Using handle program can read window caption".
This is what the line System::Call "user32.dll::GetWindowText(i r0, t r1, i r3) i.r4" does ? Right ?
Well I try this ( from reading your previous code )
But that return nohing ( I try to have the caption in the messagebox )
outfile "test.exe"
Section "Install"
StrCpy $9 0
loop:
FindWindow $0 '#32770' '' 0 $0
System::Call "user32.dll::GetWindowText(i r0, t r1, i r3) i.r4"
StrCpy $6 $1
MessageBox MB_OK|MB_ICONSTOP $6
IntOp $9 $9 + 1
StrCmp $9 3 0 loop
SectionEnd
Can you help me once again please ? :)
Takhir
18th November 2004 13:31 UTC
Caption text is second parameter, use $1 in the MessageBox.
StrCpy copies from $1 to $6 first part of caption only ($5 is length).
You have nothing because not defines buffer length (last parameter, MSDN please :)
Comm@nder21
18th November 2004 16:12 UTC
#32770 window class - few and not installer dialog windows may present on the desktop
damn :)
improved and shortened the code a bit:
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "$(^Name)") i .r0 ?e'
Pop $0
StrCmp $0 0 ok
MessageBox MB_OK|MB_ICONEXCLAMATION "Installer already running."
StrLen $0 "$(^Name)"
loop:
FindWindow $1 '#32770' '' 0 $1
IntCmp $1 0 ok
System::Call "user32.dll::GetWindowText(i r1, t .r2, i ${NSIS_MAX_STRLEN}) i."
StrCpy $2 $1 $0
StrCmp $2 "$(^Name)" 0 loop
System::call "user32::SetWindowPos(i r1, i -1, i 0, i 0, i 0, i 0, i 0x02|0x01) i."
Abort
ok:
externe
18th November 2004 17:41 UTC
Well, I try a lot of time... But impossible to open MessageBox(s) with the name of the caption of each of window...
:(