November 08, 2025
11 11 11 AM

Sendkeys Example

param(
  [Parameter(Mandatory=$true)]
  [string]$Text,
  [int]$DelaySeconds = 5,
  [switch]$EnterAfter,
  [string]$AppTitle,             # optional: exact window title to focus
  [ValidateSet('SendInput','Paste','Auto')]
  [string]$Method = 'Auto'
)

# --- Win32 helpers: SetForegroundWindow + SendInput (raw Unicode) ---
Add-Type -TypeDefinition @"
using System;
using System.Text;
using System.Runtime.InteropServices;

public static class WinApi {
  [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

  [DllImport("user32.dll", SetLastError=true)]
  public static extern bool SetForegroundWindow(IntPtr hWnd);

  [DllImport("user32.dll", SetLastError=true)]
  public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

  [StructLayout(LayoutKind.Sequential)]
  struct INPUT { public uint type; public InputUnion U; }
  [StructLayout(LayoutKind.Explicit)]
  struct InputUnion {
    [FieldOffset(0)] public KEYBDINPUT ki;
    [FieldOffset(0)] public MOUSEINPUT mi;
    [FieldOffset(0)] public HARDWAREINPUT hi;
  }
  [StructLayout(LayoutKind.Sequential)]
  struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; }
  struct MOUSEINPUT { public int dx,dy; public uint mouseData,dwFlags,time; public IntPtr dwExtraInfo; }
  struct HARDWAREINPUT { public uint uMsg,wParamL,wParamH; }

  [DllImport("user32.dll", SetLastError=true)]
  static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

  const uint INPUT_KEYBOARD=1, KEYEVENTF_UNICODE=0x0004, KEYEVENTF_KEYUP=0x0002;
  const ushort VK_CONTROL=0x11, VK_V=0x56, VK_RETURN=0x0D;

  static void SendUnicodeChar(char c){
    INPUT down=new INPUT(); down.type=INPUT_KEYBOARD; down.U.ki.wScan=c; down.U.ki.dwFlags=KEYEVENTF_UNICODE;
    INPUT up=new INPUT();   up.type=INPUT_KEYBOARD;   up.U.ki.wScan=c;   up.U.ki.dwFlags=KEYEVENTF_UNICODE|KEYEVENTF_KEYUP;
    INPUT[] arr=new INPUT[]{down,up};
    SendInput((uint)arr.Length, arr, System.Runtime.InteropServices.Marshal.SizeOf(typeof(INPUT)));
  }
  static void SendVk(ushort vk, bool up){
    INPUT i=new INPUT(); i.type=INPUT_KEYBOARD; i.U.ki.wVk=vk; i.U.ki.dwFlags=up?KEYEVENTF_KEYUP:0;
    SendInput(1, new INPUT[]{ i }, System.Runtime.InteropServices.Marshal.SizeOf(typeof(INPUT)));
  }

  public static void TypeString(string s){
    foreach(char c in s) SendUnicodeChar(c);
  }
  public static void PressEnter(){
    SendVk(VK_RETURN, false); SendVk(VK_RETURN, true);
  }
  public static void Paste(){
    SendVk(VK_CONTROL,false); SendVk(VK_V,false); SendVk(VK_V,true); SendVk(VK_CONTROL,true);
  }
  public static bool FocusExactTitle(string title){
    IntPtr h = FindWindow(null, title);
    if (h==IntPtr.Zero) return false;
    ShowWindow(h, 5); // SW_SHOW
    return SetForegroundWindow(h);
  }
}
"@

# --- Optionally focus a specific window (exact title) ---
if ($AppTitle) {
  $focused = [WinApi]::FocusExactTitle($AppTitle)
  if (-not $focused) { Write-Host "⚠️ Window titled '$AppTitle' not found. Continuing without focusing."; }
}

Write-Host "⏳ You have $DelaySeconds second(s) to click/focus the target box..."
Start-Sleep -Seconds $DelaySeconds

# --- Choose method ---
if ($Method -eq 'Auto') {
  # If the text is very long or contains lots of SendKeys-problem chars, paste is safer.
  if ($Text.Length -gt 200 -or $Text -match '[\{\}\+\%\^\~\(\)]') { $Method='Paste' } else { $Method='SendInput' }
}

switch ($Method) {
  'SendInput' {
    [WinApi]::TypeString($Text)
    if ($EnterAfter) { [WinApi]::PressEnter() }
  }
  'Paste' {
    # Clipboard paste avoids any special-char interpretation entirely
    Set-Clipboard -Value $Text
    [WinApi]::Paste()
    if ($EnterAfter) { [WinApi]::PressEnter() }
  }
}

Save as Type-Text.ps1, then run:
.\Type-Text.ps1 -Text ‘MyP@ss;word123’ -DelaySeconds 5 -EnterAfter

$ws = New-Object -ComObject WScript.Shell
Start-Sleep 5
$ws.SendKeys("}}}}")   # results in: }}

Leave a Reply

Your email address will not be published. Required fields are marked *