解救自己的小工具,部分遠端環境不能使用複製貼上功能,有些是系統不支援,有些基於安全原則(例如:Windows RDP 可透過群組原則 Do not allow Clipboard redirection 停用)或需要特別設定,伺服器非我方管理,無計可施。

此一限制造成不少困擾,像是筆記裡的超長指令,只能認命敲完;最討厭的是系統控管的動態產生密碼,亳無規則穿插滿滿的特殊符號,敲錯三次會鎖帳號,但不管怎麼睜大眼睛小心輸入,還是常三條命只剩一條才成功 Orz (都有剁手指的衝動惹) 應該是因為我的命盤破軍坐打字宮(咦?)的關係,打錯字是躲不過的宿命,寫文章總是滿篇錯字也源於此。(謎:不要瞎掰好嗎?)

為了避免有一天真的氣到剁手,我想寫個讓我選取文字後模擬打字輸入的手指保護程式。花點心思應該可以找到現成的軟體或工具,但我想用最具可攜性的 PowerShell 自己寫(理由)。

廢話不多說,直接上 Code:

param (
    [int]$Delay = 5, # delay seconds
    [switch]$Enter, # append ENTER key
    [switch]$Raw, # raw mode, don't escape special characters
    [switch]$Mask, # mask password
    [switch]$Password # mask + append ENTER key
)
$ErrorActionPreference = 'Stop'
$text = Get-Clipboard -TextFormatType Text
$disp = $text
$maxLen = 256
if ($Password) {
    $Mask = $true
    $Enter = $true
}
if ($mask -and $disp.Length -gt 2) {
    $disp= $disp.Substring(0,1) + ('*' * $disp.Length) + $disp.Substring($disp.Length - 1)
}
if ($disp.Length -gt $maxLen) {
    $disp = $disp.Substring(0, $maxLen) + '...'
}

Write-Host "Get Text from Clipboard:"
Write-Host $disp -ForegroundColor Cyan
Write-Host
$waitSecs = $Delay;
$progressTitle = "Paste Countdown"
for ($i = $waitSecs; $i -gt 0; $i--) {
    Write-Progress -Activity $progressTitle -Status "$i seconds..." -PercentComplete ($i / $waitSecs * 100)
    Start-Sleep -Seconds 1
    $host.UI.RawUI.CursorPosition.X = 0
}
Write-Progress $progressTitle -Completed 
$lines = $text.Split("`n") 
Add-Type -AssemblyName System.Windows.Forms
for ($i = 0; $i -lt $lines.Length; $i++) {
    $keys = $lines[$i]
    if (-not $Raw) {
        $keys = [regex]::Replace($keys, "[+^%~()\{\}]", { param ($m) return "{" + $m.Value + "}" })
        $keys = $keys.Replace("`r", '')
        $keys = $keys.Replace("`t", "{TAB}")
    }
    [System.Windows.Forms.SendKeys]::SendWait($keys)
    Start-Sleep -Milliseconds 100
    if ($i -lt ($lines.Length - 1) -and !$Raw) {
        [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
    }
}
if ($Enter) {
    [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
}

程式用到一個老 API,System.Windows.Forms.SendKeys.SendWait(),傳入要輸入的文字即可(支援中文字元),特殊按鍵用 {TAB}{ENTER}{ESC}{HOME} ... 等表示(完整指令清單)。

使用方法很簡單,先選取複製要輸入內容,執行 Paste-As-KeyStrokes.ps1 程式會等待五秒後模擬鍵盤輸入剪貼簿中的文字,-Delay n 可指定等待 N 秒,-Enter 會在輸完文字後加按 Enter,-Raw 則允許將複製文字視為原始控制指令送給 SendWait();-Mask 用於密碼,只保留頭尾明碼,其餘換成 * 符號;-Password 等於 -Mask + -Enter,遮蔽字元並在輸入完成後按 Enter。

以下是簡單展示,原本不支援剪下貼上的 Debian 遠端桌面,輸入又長又複雜的 30 字元長密碼,完成 nano 建立 test.txt、存檔、顯示內容後刪除的一連串操作(使用 -Raw 以輸入 Ctrl-O、Ctrl-X),以及展示 Windows RDP 可直接傳入中文字元的功能。

操作展示

工具箱再添好用工具一件。

This is a straightforward PowerShell script designed to paste text content from the clipboard as keystrokes, useful for scenarios that do not support the standard copy-and-paste function.


Comments

# by Chia

這發明真是太棒了! 有種吃了無敵星星的感覺

# by 小熊子

這太讚了,造福眾生~

# by alopex

無敵好用~都想去買可以自動執行腳本的鍵盤滑鼠了

# by Valor

看到這好東西也手癢用AutoHotKey試試,請笑納 #Requires AutoHotkey v2.0 ; 監聽 alt+1 的快捷鍵 !1::{ SetKeyDelay 50 clipboardBackup := A_Clipboard ; 儲存當前剪貼簿內容 modifiedClipboard := StrReplace(clipboardBackup, "`r`n", "`n") ; 替換換行符 A_Clipboard := modifiedClipboard ; 使用修改後剪貼簿內容 Send "{Alt down}{Tab}" Sleep(500) Send "{Alt up}" Sleep(1000) SendEvent "{Raw}" A_Clipboard ; 模擬鍵盤輸入剪貼簿內容 clipboardBackup := "" } 加入了切換到前一個視窗自動貼上的功能,SetKeyDelay可調輸入速度

# by Jeffery

感謝大大的分享!! 不過我發現貼特殊符號複製會有問題 To: Valor 感謝樓上分享 AutoHotKey 順利改動Windows Server 登入密碼XDD

# by JW

請問在 mac 上執行會出現錯誤訊息,要怎麼處理? Get-Clipboard: Paste-As-KeyStrokes.ps1:9 Line | 9 | $text = Get-Clipboard -TextFormatType Text | ~~~~~~~~~~~~~~~ | A parameter cannot be found that matches parameter name 'TextFormatType'. 把 -TextFormatType Text 拿掉之後,改出現: Add-Type: Paste-As-KeyStrokes.ps1:36 Line | 36 | Add-Type -AssemblyName System.Windows.Forms | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | Cannot find path '/Users/(username)/Documents/System.Windows.Forms.dll' because it does not exist.

# by Jeffrey

to JW,小工具是靠 Window Form API 模擬鍵盤輸入,不適用 Mac。Mac 要玩自動化,可能要考慮 Hammerspoon、AutoHotKey for Mac 之類的解決方案。

# by 小熊子

若有群組規則擋掉ps1的執行權限,可使用以下指令針對單一ps1檔案執行權限開放: powershell.exe -noprofile -executionpolicy bypass -file C:\DarkthreadTools\Paste-As-KeyStrokes.ps1

Post a comment