簡體   English   中英

NSIS-查看給定進程是否顯示了窗口

[英]NSIS - See if a given process has shown a window

我通過NSIS安裝程序中的ExecShell運行某個進程。 該過程需要一段時間(可能需要5到40秒)才能開始,在此期間我希望NSIS窗口保持可見。

問題在於,雖然進程本身幾乎是立即啟動的,但它是在用戶看到任何東西之前的某個時間,因此我希望NSIS安裝程序窗口在啟動進程的主窗口之前一直保持可見(或顯示與此相關的任何窗口)。

因此,我需要知道的是如何從ExecShell獲取processid(由於其他原因不能使用Exec或ExecWait),然后如何使用該進程ID來查看窗口是否已顯示(我知道我可以通過簡單的睡眠,檢查,goto循環,所以基本上我想弄清楚它的檢查部分)?

因此,如何確切地知道我使用ShellExec生成的進程是否顯示了GUI。 這需要在Windows XP SP3及更高版本中運行。

謝謝。

RequestExecutionLevel user
Page InstFiles

!include LogicLib.nsh
!include WinMessages.nsh ; For SW_*

Var IsSlowFakeApp ; We can also pretend to be a silly little app that is slow to start up, this is just so the example code has no external dependencies

Function .onInit
StrCpy $0 $CMDLINE 1 -1
${If} $0 == "?"
    StrCpy $IsSlowFakeApp 1
    Sleep 3333
${EndIf}
FunctionEnd


Function StartMyAppAndWaitForWindow
StrCpy $0 "$ExePath" ; Application
StrCpy $1 "?" ; Parameters
!define SEE_MASK_NOCLOSEPROCESS 0x40
DetailPrint 'Starting "$0" $1'
System::Store S
System::Call '*(i60,i${SEE_MASK_NOCLOSEPROCESS},i$hwndparent,i0,tr0,tr1,i0,i${SW_SHOW},i,i,i,i,i,i,i)i.r0'
System::Call 'SHELL32::ShellExecuteEx(ir0)i.r1'
${If} $1 <> 0
    System::Call '*$0(i,i,i,i,i,i,i,i,i,i,i,i,i,i,i.r1)'
    System::Call 'USER32::WaitForInputIdle(ir1,2000)i'

    System::Call 'KERNEL32::GetProcessId(ir1)i.r2' ; MSDN says this function is XP.SP1+
    StrCpy $3 $2 ; Not found a window yet, keep looping

    ; Call EnumWindows until we find a window matching our target process id in $2
    System::Get '(i.r5, i) iss'
    Pop $R0
    callEnumWindows:
        System::Call 'USER32::EnumWindows(k R0, i) i.s'
        loopEnumWindows:
            Pop $4
            StrCmp $4 "callback1" 0 doneEnumWindows
            System::Call 'USER32::GetWindowThreadProcessId(ir5,*i0r4)'
            ${If} $4 = $2
                System::Call 'USER32::IsWindowVisible(ir5)i.r4'
                ${IfThen} $4 <> 0 ${|} StrCpy $3 0 ${|} ; Found a visible Window
            ${EndIf}
            Push $3 ; EnumWindows callback's return value
            System::Call "$R0"
            Goto loopEnumWindows
        doneEnumWindows:
    ${If} $3 <> 0
        Sleep 1000
        Goto callEnumWindows
    ${EndIf}
    System::Free $R0

    ; Hide installer while app runs
    /*HideWindow
    System::Call 'KERNEL32::WaitForSingleObject(ir1,i-1)'
    BringToFront*/
    System::Call 'KERNEL32::CloseHandle(ir1)'
${EndIf}
System::Free $0
System::Store L
FunctionEnd

Section
${If} $IsSlowFakeApp <> 0
    SetCtlColors $HWNDPARENT 0xffffff 0xdd0000
    FindWindow $0 "#32770" "" $HWNDPARENT
    SetCtlColors $0 0xffffff 0xdd0000
    DetailPrint "This is a fake slow app and it will close soon..."
    Sleep 5555
    Quit
${Else}
    Call StartMyAppAndWaitForWindow
${EndIf}
SectionEnd

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM