Archive: Set focus to installer window


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


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.


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

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]

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

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.

Yes, it's really works !!! :up:

That's was my typo error :(

thanks a lot
kobus


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 :)

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


why didn't you try the usual way?

FindWindow $1 "#32770"

should work for every title ...

Doesn't work :p

-Stu


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 :)

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

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



!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

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.


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


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 :)

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).


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 ? :)

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 :)


#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:

Well, I try a lot of time... But impossible to open MessageBox(s) with the name of the caption of each of window...
:(