PowerShell SendKeys粘贴指令无法在cmd/powershell窗口生效问题
问题根本原因
传统conhost.exe托管的cmd、powershell.exe控制台窗口,默认不响应Ctrl+V粘贴快捷键:控制台会将Ctrl+V解析为ASCII控制字符0x16,终端显示为^V,不会触发粘贴逻辑。
记事本等标准GUI程序原生处理WM_PASTE消息、识别Ctrl+V快捷键,因此相同脚本在记事本中可正常运行。
补充两个相关细节:
- Windows 10 1703及之后版本的控制台虽然新增了Ctrl快捷键支持,但该选项默认未开启,且可被用户或组策略手动关闭,不能作为通用兼容方案依赖。
- 问题和
Set-Clipboard、SendKeysAPI本身无关,是控制台窗口的按键处理规则和GUI程序不同导致的。选择剪贴板粘贴替代逐字SendWait的思路完全正确,长文本场景下粘贴的效率优势非常明显。
解决方案
方案1:直接发送WM_PASTE消息(兼容性最好)
不模拟按键,直接通过Win32 API向目标控制台窗口发送粘贴消息,不受控制台快捷键配置影响,全版本Windows通用。
# 导入所需Win32函数 Add-Type @" using System; using System.Runtime.InteropServices; public class Win32Interop { [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); } "@ $text = "HELLO" Start-Process cmd.exe Start-Sleep -Milliseconds 500 # 等待窗口启动并获得焦点 Set-Clipboard -Value "echo $text" Start-Sleep -Milliseconds 100 # 向当前前台窗口发送WM_PASTE(0x0302)消息 $targetWindow = [Win32Interop]::GetForegroundWindow() [Win32Interop]::SendMessage($targetWindow, 0x0302, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null Start-Sleep -Milliseconds 100 [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
方案2:调用控制台原生菜单粘贴快捷键(无代码侵入)
所有版本Windows的控制台默认支持通过窗口控制菜单触发粘贴:按Alt+Space打开控制菜单,按E展开编辑子菜单,按P触发粘贴。只需要把原代码中模拟^V的部分替换为模拟该组合键即可,不需要额外加载Win32 API:
$text = "HELLO" Start-Process cmd.exe Start-Sleep -Milliseconds 300 Set-Clipboard -Value "echo $text" Start-Sleep -Milliseconds 300 # %代表Alt键,通过控制台内置菜单快捷键触发粘贴 [System.Windows.Forms.SendKeys]::SendWait("% ep") Start-Sleep -Milliseconds 300 [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
注意该方案在控制台窗口控制菜单被组策略禁用时会失效,兼容性略低于方案1。
方案3:适配Windows Terminal环境
如果目标程序运行在Windows Terminal中,其默认支持Ctrl+V粘贴,原有脚本不需要修改即可正常运行,该问题仅存在于传统conhost托管的控制台窗口。
内容的提问来源于stack exchange,提问作者Y108
相关产品推荐
相关产品推荐

