CmdLets/Master/Send-KeyToProcess.ps1
|
# Load required assemblies Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # Add Win32 API functions for window control Add-Type @" using System; using System.Runtime.InteropServices; public class WinAPI { [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); } "@ Function Send-KeyToProcess { <# .SYNOPSIS Brings a target application's window to the foreground and sends simulated keystrokes to it. .DESCRIPTION The Send-KeyToProcess function locates a running process by its name, retrieves its main window handle, and brings it to the foreground using Win32 API integration (`SetForegroundWindow`). It then utilizes `System.Windows.Forms.SendKeys::SendWait` to simulate keystrokes or keyboard shortcuts (such as modifier keys like `+` for Shift, `^` for Ctrl, and `%` for Alt, alongside special keys like `{Enter}`). .PARAMETER ProcessName The name of the target process (excluding the `.exe` extension) that should receive the keystrokes. .PARAMETER Key The key sequence or combination string to send, following standard .NET SendKeys syntax (e.g., "^c" for Copy, "%{F4}" to close, or "{Enter}"). .EXAMPLE Send-KeyToProcess -ProcessName "notepad" -Key "Hello World{Enter}" Description: Brings Notepad to the foreground and types "Hello World" followed by an Enter keystroke. .NOTES Prerequisites: - Requires `System.Windows.Forms` and the custom `WinAPI` C# type to be loaded in the session. - Requires the target process to have an active main window handle (`MainWindowHandle`). .LINK https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys.sendwait #> [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string]$ProcessName, [Parameter(Mandatory=$true)] [string]$Key ) <# Supported Keys: Modifier Symbol Example Shift + "+A" → Shift + A Ctrl ^ "^C" → Ctrl + C Alt % "%F4" → Alt + F4 {Enter} {TAB} {ESC} {UP} {DOWN} {LEFT} {RIGHT} F1 to F12 -- Unsure which is correct {F1} to {F12} -- Unsure which is correct #> try { # Get the process $proc = Get-Process -Name $ProcessName -ErrorAction Stop | Select-Object -First 1 if (-not $proc.MainWindowHandle -or $proc.MainWindowHandle -eq 0) { Write-Error "Process '$ProcessName' has no main window." return } # Bring window to front #[WinAPI]::ShowWindowAsync($proc.MainWindowHandle, 5) | Out-Null # 5 = SW_SHOW #Start-Sleep -Milliseconds 200 [WinAPI]::SetForegroundWindow($proc.MainWindowHandle) | Out-Null Start-Sleep -Milliseconds 200 # Send the key [System.Windows.Forms.SendKeys]::SendWait($Key) Write-Host "Sent key '$Key' to process '$ProcessName'." } catch { Write-Error "Error: $_" } } |