Send-Keys: Send a sequence of keys to an application window based on Window Title

Topics: Archive - Toolkit Extensions
Jul 9, 2014 at 11:13 PM
I am using a custom logging function posted on another thread in this forum. Write-ErrorStack function is also posted to another thread in this forum.
Function Send-Keys
        Send a sequence of keys to an application window
        This Send-Keys script send a sequence of keys to an application window. 
    .PARAMETER WindowTitle
        The title of the application window. This can be a partial title.
        The sequence of keys to send
    .PARAMETER WaitSeconds
        An optional number of seconds to wait after the sending of the keys
        Send-Keys "foobar - Notepad" "Hello world"
    Send the sequence of keys "Hello world" to the application titled "foobar - Notepad".
        Send-Keys "foobar - Notepad" "Hello world" -WaitSeconds 5
        Send the sequence of keys "Hello world" to the application titled "foobar - Notepad" and wait 5 seconds.
        New-Item foobar.txt -ItemType File
        notepad foobar.txt
        Send-Keys "foobar - Notepad" "Hello world{ENTER}Ciao mondo{ENTER}" -WaitSeconds 1
        Send-Keys "foobar - Notepad" "^s"

        This command sequence creates a new text file called foobar.txt, opens the file using notepad.exe,
        writes some text, and saves the file using notepad.


        ${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
        $PSParameters = New-Object -TypeName PSObject -Property $PSBoundParameters
        Write-Log -Message "Function Start" -Component ${CmdletName} -Severity 1
        If (-not [string]::IsNullOrEmpty($PSParameters))
            Write-Log -Message "Function invoked with bound parameters [$PSParameters]" -Component ${CmdletName} -Severity 1
            Write-Log -Message "Function invoked without any bound parameters" -Component ${CmdletName} -Severity 1
            # Load assembly containing class System.Windows.Forms.SendKeys
            Add-Type -AssemblyName System.Windows.Forms -ErrorAction 'Stop'
            # Add a C# class to access the WIN32 API SetForegroundWindow
            $SetForegroundWindow = @"
                using System;
                using System.Runtime.InteropServices;
                public class WINDOW
                    [return: MarshalAs(UnmanagedType.Bool)]
                    public static extern bool SetForegroundWindow(IntPtr hWnd);
            If (-not ([System.Management.Automation.PSTypeName]'WINDOW').Type)
                Add-Type $SetForegroundWindow -ErrorAction 'Stop'
            # Get the process with the specified window title
            $Process = Get-Process -ErrorAction 'Stop' | Where-Object { $_.MainWindowTitle.Contains($WindowTitle) }
            If ($Process)
                # Get the window handle of the first process only if there is more than one process returned
                $ProcessHandle = $Process[0].MainWindowHandle
                # Bring the process to the foreground
                $ActivateWindow = [WINDOW]::SetForegroundWindow($ProcessHandle)
                # Send the Key sequence
                # Info on Key input at:
                If ($ActivateWindow)
                    # Failed to bring the window to the foreground. Do nothing.
                If ($WaitSeconds)
                    Start-Sleep -Seconds $WaitSeconds
            Write-Log -Message "Failed to Send Keys `n$(Write-ErrorStack)" -Component ${CmdletName} -Severity 3
        Write-Log -Message "Function End" -Component ${CmdletName} -Severity 1
Aug 2, 2014 at 1:01 PM
This is a function we think could be very useful so if it's OK with you we're going to make a few tweaks and add it in to the core toolkit.

Thanks for the excellent contributions!

Aug 3, 2014 at 1:26 AM
Absolutely, go for it.