text_check 走的是产品同一条路径(Session::send_text → v3 线格式 → agent SendInput KEYEVENTF_UNICODE),手机掉线也能先把 Windows 半段验实。 参数是十进制 code unit 列表而不是自然语言字符串:命令行到 Rust 的编码往返 会引入与本轮无关的变量,由 PowerShell 从 .NET 字符串取 char[] 更忠实。 proof 脚本刻意用自有 WinForms 靶窗而非记事本:Win11 记事本所有标签页同进程, 本机当时开着用户文档,往里注入等于改用户文件。靶窗自报文本(写文件), 判据不依赖截图和 OCR。注入前后各断言一次前台窗口——SendInput 打的是前台, 靶窗不在前台时的注入会进别的应用,宁可失败也不误注入。
63 lines
2.1 KiB
PowerShell
63 lines
2.1 KiB
PowerShell
# 2b V6/V7 proof target: a dedicated WinForms window we own.
|
|
# ASCII-only source (PS 5.1 decodes BOM-less .ps1 as GBK; see personal lessons).
|
|
#
|
|
# Launched by text_injection_proof.ps1. Shows a topmost empty TextBox, writes
|
|
# its current text to ResultFile (UTF-8 with BOM) on every change, exits when
|
|
# StopFile appears. The proof injects through the remote-control pipeline and
|
|
# polls ResultFile - so "what arrived on the controlled desktop" is reported
|
|
# by the receiving application itself, not by a screenshot or OCR.
|
|
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$PidFile,
|
|
[Parameter(Mandatory = $true)][string]$ResultFile,
|
|
[Parameter(Mandatory = $true)][string]$StopFile
|
|
)
|
|
$ErrorActionPreference = "Stop"
|
|
Add-Type -AssemblyName System.Windows.Forms
|
|
Add-Type -AssemblyName System.Drawing
|
|
|
|
# Event handler scriptblocks resolve script-scoped vars; make that explicit
|
|
# instead of relying on the param locals staying on a visible scope chain.
|
|
$script:PidFile = $PidFile
|
|
$script:ResultFile = $ResultFile
|
|
$script:StopFile = $StopFile
|
|
$script:lastWritten = $null
|
|
|
|
$form = New-Object System.Windows.Forms.Form
|
|
$form.Text = "RemoteTextTarget"
|
|
$form.ClientSize = New-Object System.Drawing.Size(420, 140)
|
|
$form.TopMost = $true
|
|
$form.StartPosition = "Manual"
|
|
$form.Location = New-Object System.Drawing.Point(80, 80)
|
|
|
|
$tb = New-Object System.Windows.Forms.TextBox
|
|
$tb.Multiline = $true
|
|
$tb.Font = New-Object System.Drawing.Font("Segoe UI", 16.0)
|
|
$tb.Dock = "Fill"
|
|
$form.Controls.Add($tb)
|
|
|
|
$timer = New-Object System.Windows.Forms.Timer
|
|
$timer.Interval = 150
|
|
$timer.Add_Tick({
|
|
if (Test-Path $script:StopFile) {
|
|
$form.Close()
|
|
return
|
|
}
|
|
if ($tb.Text -ne $script:lastWritten) {
|
|
$script:lastWritten = $tb.Text
|
|
$enc = New-Object System.Text.UTF8Encoding($true)
|
|
[System.IO.File]::WriteAllText($script:ResultFile, $tb.Text, $enc)
|
|
}
|
|
if (-not $tb.Focused) { [void]$tb.Focus() }
|
|
})
|
|
|
|
$form.Add_Shown({
|
|
$form.Activate()
|
|
[void]$tb.Focus()
|
|
[System.IO.File]::WriteAllText($script:PidFile, "$PID")
|
|
})
|
|
|
|
$timer.Start()
|
|
[void]$form.ShowDialog()
|
|
$timer.Stop()
|