Search code examples
powershellsendkeyspowershell-5.0

Alternative to time delay while installing exe through PowerShell?


I have a software exe which I am trying to install via PowerShell. It's working fine. I am using SendKeys to navigate through the installation GUI. I have given delay between two SendKeys commands, because software takes some time between two steps, but that installation time varies from computer to computer.

My question is how can I bypass this time delay dependency in SendKeys? I have tried AppActivate but its of no use for me. Is there any alternative to delay?


Solution

  • Sure.

    I've converted Nitesh's C# function to a Powershell script

    $signature_user32_GetForegroundWindow = @"
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
    "@
    
    $signature_user32_GetWindowText = @"
    [DllImport("user32.dll")]
    public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
    "@
    
    $foo = `
        Add-Type -MemberDefinition $signature_user32_GetForegroundWindow `
            -Name 'user32_GetForegroundWindow' `
            -Namespace 'Win32' `
            -PassThru
    
    $bar = `
        Add-Type -MemberDefinition $signature_user32_GetWindowText `
            -Name 'user32_GetWindowText' `
            -Namespace 'Win32' `
            -Using System.Text `
            -PassThru
    
    [int]$nChars = 256
    [System.IntPtr] $handle = New-object 'System.IntPtr'
    [System.Text.StringBuilder] $Buff = New-Object 'System.Text.StringBuilder' `
        -ArgumentList $nChars
    
    $handle = $foo::GetForegroundWindow()
    $title_character_count = $bar::GetWindowText($handle, $Buff, $nChars)
    If ($title_character_count -gt 0) { Write-Output $Buff.ToString() }
    

    There is a lot going on here. Lemme explain a little of what I did.

    1. I've created two method signatures (the bit in the here-string); one for each function we're calling.
    2. I use those signatures to create corresponding types. Again, one for each method.
    3. For the GetWindowType (which passes the title back in a string and needs a reference to System.Text), I pass in the System.Text namespace in the -Using parameter.
    4. Behind the scenes, PowerShell adds references to the System and System.Runtime.InteropServices so no need to worry about those.
    5. I create my string size ($nChars), window pointer ($handle), and window title buffer ($Buff)
    6. I call the functions through the type-pointer: $foo... and $bar...

    Here is what I get when I run all this...

    enter image description here

    Whenever I have to call the Windows API (which isn't really my thing), I reference the following two articles:

    I hope this helps!