Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell wait application to launch

Tags:

powershell

I have the following script to launch an application:

add-type -AssemblyName microsoft.VisualBasic
add-type -AssemblyName System.Windows.Forms
$args = "arguments"
$proc = Start-Process -PassThru "path" -ArgumentList $args
start-sleep -Seconds 5
[Microsoft.VisualBasic.Interaction]::AppActivate($proc.Id)
[System.Windows.Forms.SendKeys]::SendWait("~")

I use this script to launch several windows forms applications that need user interaction to start (i.e. push a start button). So far I've been sleeping the script 5 seconds to allow the application to launch. I tried to run this script in a variety of computers with different processing capabilities, but did not work in all computers, some launch the application slower than others, when the app took more than 5 seconds to launch the app the script fails, because the AppActivate could not find the PID. I don't want to try different sleeping times for each computer, because I have to run this script in more than 100 computers at boot time.

I would like to know if there is a way to wait for the application to launch in a event driven way.

UPDATE:

The WaitForInputIdle does not work in all applications I tried to start. It returns immediately (successfully because it's returning true) and the AppActive method throws an exception.

like image 395
rena Avatar asked Jul 29 '26 01:07

rena


2 Answers

I suggest you to avoid using "Sleep" to synchronize system objects (it's never a good solution). As far as you are starting Windows Forms application I suggest you to use Process.WaitForInputIdle Method.

 $p = [diagnostics.process]::start("notepad.exe", "D:\temp\1mbfile.txt")
 $p.WaitForInputIdle(5000);

using it in a loop you can test alternatively test if the input is idle (application is started and waiting) or if the application is stopped ($p.HasExited -eq $true).

do
 {
   if ($p.HasExited -eq $true)
   {
     break
   }
 } while ($p.WaitForInputIdle(5000) -ne $true)
like image 180
JPBlanc Avatar answered Jul 30 '26 16:07

JPBlanc


So, I finally wrote this workaround since WaitForInputIdle does not work with all my applications and I was not able to figure out why.

do{
    if ($proc.MainWindowHandle -ne 0)
   {
        break
   }
   $proc.Refresh() 
} while ($true)

I am not sure if this is the best approach; anyway, I wanted to share this.

like image 42
rena Avatar answered Jul 30 '26 16:07

rena