Announcement

Collapse
No announcement yet.

SetForegroundWindow by PID

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • SetForegroundWindow by PID

    Hello everyone, this is my first post so please be gentle - if there is something wrong about the question format, let me know.

    My intention is to bring a window back to foreground with my Process ID.

    Here is what I'v found so far:

    code:
    Function .onGUIEnd
    FindWindow $0 "WindowClass" "Title"
    IsWindow $0 0 +2
    System::Call 'user32::SetForegroundWindow(i r0)'

    It works, but to make absolutely sure choosing the correct application (in case of multilingual or same name of windows), I would rather bring the window to foreground providing the process ID, not the window class or the title. I already have my necessary PID.

    Do you have any ideas how I can perform the SetForegroundWindow with PID?

  • #2
    PHP Code:
    FindWindow $....
    System::Call 'USER32::GetWindowThreadProcessId(p$0,*i0r1)'
    ${If} $$mypid ... 
    It is possible to call FindWindow in a loop by using the childafter parameter...
    IntOp $PostCount $PostCount + 1

    Comment


    • #3
      Thank you very much. I'll try it out the next days.

      Comment


      • #4
        Unfortunately it doesn't work:
        Error: unterminated string parsing line at C:\InnoSetup-Software\Source - NSIS\Focus.nsi:52

        -> System::Call 'USER32::GetWindowThreadProcessId(p$0,*i0r1)

        !include LogicLib.nsh
        ;!define mypid "3044"

        Function .onGUIEnd
        FindWindow $0 "" "Aqua'S KeyTest"
        IsWindow $0 0 +2
        System::Call 'USER32::GetWindowThreadProcessId(p$0,*i0r1)
        ${If} $1 == $mypid
        System::Call 'user32::SetForegroundWindow(i r0)'
        ${EndIf}
        FunctionEnd



        Can you send me a little more specific code example I can work with?

        Comment


        • #5
          Just a typo, missing the final '. I edited my post.
          IntOp $PostCount $PostCount + 1

          Comment


          • #6
            thanks, the line is accepted now.

            But I'm afraid I dont know how to search trough all windows in a loop until the process id matches the defined one (that was passed as argument to .exe). That's the final taget for my project.

            The code I've now shows endless the same item and can't compare the id I gave as parameter (not even when hardcoded as variable) - it always says they match.

            Can you help me a little bit with this task as I'm very new to NSIS and struggling with the help websites at all?

            Comment


            • #7
              Got a few steps close to my aim, but fails if there are two instances of the Windows. The script should go through all one after the other...



              Function .onGUIEnd
              loop:
              Pop $0
              StrCpy $mypid "2424"
              ;FindWindow $0
              ;IsWindow $0 0 +2
              ;System::Call 'user32::SetForegroundWindow(i r0)'

              FindWindow $0 "" "AquaKeyTest"
              IsWindow $0 0 +2
              System::Call 'USER32::GetWindowThreadProcessId(p$0,*i0r1)'
              MessageBox MB_OK "mypid(Gesucht)=$mypid und PID(Gefunden)=$1"
              ${If} $1 = $mypid
              MessageBox MB_OK "Test"
              System::Call 'user32::SetForegroundWindow(i r0)'
              IsWindow $0 done
              ${EndIf}
              System::Call "$R0"
              goto loop

              Comment


              • #8
                PHP Code:
                !include LogicLib.nsh
                !include WinMessages.nsh
                ExecShell 
                '' Notepad '' SW_SHOWMINIMIZED Instance we don't care about
                !define /IfNDef STARTF_USESHOWWINDOW 0x0001
                !define /IfNDef SW_SHOWMINNOACTIVE 7
                System::Call '
                *(&l${NSIS_PTR_SIZE},p,p,p,i,i,i,i,i,i,i,${STARTF_USESHOWWINDOW},${SW_SHOWMINNOACTIVE},p,p,p,p)p.r1'
                System::Call '
                *(p,p,i,i)p.r2'
                System::Call '
                KERNEL32::CreateProcess(p0,"notepad.exe",p0,p0,i0,i0,p0,p0,pr1,pr2)i.r0'
                ${If} $0 <> 0
                    System::Call "*$2(p.r3,p.r4,i.r0,i)"
                    System::Call '
                KERNEL32::CloseHandle(pr3)'
                    System::Call '
                KERNEL32::CloseHandle(pr4)'
                ${EndIf}
                System::Free $1
                System::Free $2
                ExecShell '' Notepad '' SW_SHOWMINIMIZED ; Instance we don'
                t care about
                Sleep 1234 
                Wait for Notepad to start

                !define CLASS "Notepad"
                StrCpy $""
                loop:
                FindWindow $"${CLASS}" "" "" $2
                StrCpy 
                $$1
                ${If} $1 P<> 0
                ${AndIf} $<> PID
                    System
                ::Call 'USER32::GetWindowThreadProcessId(p$1,*i0r3)'
                    
                System::Call 'USER32::IsWindowVisible(p$1)i.r4'
                    
                ${If} $= $0
                    
                ${AndIf} $<> 0
                        System
                ::Call 'USER32::SetForegroundWindow(p$1)'
                        
                System::Call 'USER32::SwitchToThisWindow(p$1,i1)'
                    
                ${Else}
                        Goto 
                loop
                    
                ${EndIf}
                ${EndIf} 
                IntOp $PostCount $PostCount + 1

                Comment


                • #9
                  !include WinMessages.nsh
                  !include LogicLib.nsh
                  StrCpy $mypid "4128" ;example PID (ok) - later this should applied from command-line parameter

                  StrCpy $2 ""
                  loop:
                  FindWindow $1 "" "Aquakeytest" "" $2 ;Windowtitle (not ok) should be determined automatically from PID
                  StrCpy $2 $1
                  ${If} $1 P<> 0
                  ;${AndIf} $0 <> 0 ; PID
                  System::Call 'USER32::GetWindowThreadProcessId(p$1,*i0r3)'
                  ;MessageBox MB_OK "mypid(Search)=$mypid und PID(Found)=$3"
                  ${If} $3 = $mypid
                  System::Call 'USER32::SetForegroundWindow(p$1)'
                  System::Call 'USER32::SwitchToThisWindow(p$1,i1)'
                  ${Else}
                  Goto loop
                  ${EndIf}
                  ${EndIf}


                  Thank you very much - I changed the code a little bit so that it compares the result with my defined PID and use an existing process in general instead of creating a new one. So far it works.
                  Now the PID and Windowtitle is necessary to know, but the Windowtitle should be created from PID automatically - is this possible?

                  Comment


                  • #10
                    Not sure I understand. If you don't know the window title you can leave it as "" like my example.

                    If you know the title and the pid is part of it then you don't even need the loop

                    StrCpy $mypid ....
                    ; if the title is "fooPIDbar"
                    FindWindow $1 "AquaKeyTest" "foo$mypidbar"
                    IntOp $PostCount $PostCount + 1

                    Comment


                    • #11
                      Yes, I don't know the title, so the query for PID is indeed necessary.

                      But if I try to leave the title blank (FindWindow $1 "" "" "" $2), it doesn't work - in this case the entry it shows does't fit (${If} $1 P<> 0 seems to fail) and it repeats the loop infinte.

                      So I have to retrieve the windotitle from pid before everything else... but how can I achieve this?

                      Comment


                      • #12
                        There is nothing stopping you from enumerating all windows if you don't know the title nor class. If your loop is infinite you have a bug somewhere.

                        PHP Code:
                        !include LogicLib.nsh
                        Section
                        StrCpy 
                        $""
                        loop:
                            
                        FindWindow $"" "" "" $2
                            StrCpy 
                        $$1
                            
                        ${If} $1 P<> 0
                                System
                        ::Call 'USER32::IsWindowVisible(p $1)i.r4'
                                
                        System::Call 'USER32::GetWindowText(p $1, t ""r5, i ${NSIS_MAX_STRLEN})'
                                
                        ${If} $!= ""
                                
                        ${AndIf} $<> 0
                                    DetailPrint 
                        "Visible window $1 has title $5"
                                
                        ${EndIf}
                                Goto 
                        loop
                            
                        ${EndIf} 
                        SectionEnd 
                        IntOp $PostCount $PostCount + 1

                        Comment


                        • #13
                          Thank you - you code works like a charm now!

                          May I ask to help me one more time?
                          How can I compare the process name instead of the PID if the process name is known only?

                          Input (search): -Process name-
                          Output (found): -Process name- for "p $1"

                          I tried with GetWindowModuleFilename, GetModuleBaseName and several others too, but never get a result at all.

                          Comment


                          • #14
                            Those functions only work for the current process. https://stackoverflow.com/questions/...me-of-a-window

                            I'd say, use one of the process plug-ins, https://nsis.sourceforge.io/PS_plug-in etc.
                            IntOp $PostCount $PostCount + 1

                            Comment


                            • #15
                              Unfortunately, I tried already. Either they don't include retrieving process name or it simply don't work.
                              I managed to call a result via wmic, but I cant get it to display each line of the variable separately.

                              Comment

                              Working...
                              X