Powershell 中的 SendKeys 方法

Powershell 中的 SendKeys 方法

我有用于自动 telnet 服务器的批处理文件,我想使用 PowerShell 执行同样的事情

批处理文件名为Script.bat:

:: Open a Telnet window
 start telnet.exe 10.84.10.85
:: Run the script
 cscript SendKeys.vbs

名为 SendKeys.vbs 的命令文件:

set OBJECT=WScript.CreateObject("WScript.Shell")
 WScript.sleep 1000
 OBJECT.SendKeys "myPassword{ENTER}"
 WScript.sleep 1000
 OBJECT.SendKeys "7{ENTER}"
 WScript.sleep 1000
 OBJECT.SendKeys "1{ENTER}"
 WScript.sleep 1000
 OBJECT.SendKeys "{ENTER}"
 WScript.sleep 1000
 OBJECT.SendKeys "{ENTER}"
 WScript.sleep 1000
 OBJECT.SendKeys "Y{ENTER}"
 WScript.sleep 3000
 OBJECT.SendKeys ""

答案1

PowerShell 没有内置模拟击键功能。

实际上,您有两个选择:COM-Automation 和 Interop。

  1. 通过 COM 发送密钥

就像在 VB(S) 中一样,您可以创建 Shell 对象和 SendKeys。以下是使用 PowerShell 的方法。

$wshell = New-Object -ComObject wscript.shell;
$wshell.SendKeys('a')

如果您想向窗口发送击键,您必须先激活它:

$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('title of the application window')
Sleep 1
$wshell.SendKeys('~')

一些击键有特殊变量,如表示 RETURN 的 ~。这里是完整列表。
激活窗口后,通常需要等待一秒钟,直到它响应,否则它会将密钥发送到 PowerShell 窗口,或者发送到任何地方。脚本主机的 SendKeys 方法可能不可靠,但幸运的是,有更好的方法。

  1. 通过 Interop 发送密钥

就像在 C# 中一样,你可以使用等待发送PowerShell 中 .NET Framework 的方法。

[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
[System.Windows.Forms.SendKeys]::SendWait("x")

如果你想激活一个窗口,可以这样做:

[void] [System.Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
[Microsoft.VisualBasic.Interaction]::AppActivate("Internet Explorer - Windows")

要睡眠,您可以使用开始-睡眠命令。

关于您原来的问题,我建议以下解决方案:

# Open a Telnet window
Start-Process telnet.exe -ArgumentList 10.84.10.85
# Run the keystrokes
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait('myPassword{ENTER}')
Start-Sleep 1
[System.Windows.Forms.SendKeys]::SendWait('7{ENTER}')
Start-Sleep 1
[System.Windows.Forms.SendKeys]::SendWait('1{ENTER}')
Start-Sleep 1
[System.Windows.Forms.SendKeys]::SendWait('{ENTER}')
Start-Sleep 1
[System.Windows.Forms.SendKeys]::SendWait('{ENTER}')
Start-Sleep 1
[System.Windows.Forms.SendKeys]::SendWait('Y{ENTER}')
Start-Sleep 1
[System.Windows.Forms.SendKeys]::SendWait('')

警告:如果您使用此方法发送密码,请格外小心,因为在调用AppActivate和调用之间激活不同的窗口SendKeys将导致密码以纯文本形式发送到不同的窗口(例如您最喜欢的信使)!

答案2

function Do-SendKeys {
    param (
        $SENDKEYS,
        $WINDOWTITLE
    )
    $wshell = New-Object -ComObject wscript.shell;
    IF ($WINDOWTITLE) {$wshell.AppActivate($WINDOWTITLE)}
    Sleep 1
    IF ($SENDKEYS) {$wshell.SendKeys($SENDKEYS)}
}
Do-SendKeys -WINDOWTITLE Print -SENDKEYS '{TAB}{TAB}'
Do-SendKeys -WINDOWTITLE Print
Do-SendKeys -SENDKEYS '%{f4}'

答案3

我对脚本做了一些修改,我有一个具有相同密码的 IP 服务器列表,我想自动 telnet 该列表并发送密钥来停用或激活 FTP 服务器。

我的脚本是:

  ## - List of IP
  $printers = get-content "C:\Dir2\servers.txt"

  foreach ($IPAddress in $printers){

   ## - Start Telnet Session:
     start-process C:\Windows\System32\telnet.exe -argumentlist $IPAddress

   ## - SendKey for each IP
     $obj = New-Object -com Wscript.Shell
     sleep -s 3
     $obj.SendKeys("MyPassword{ENTER}")
     sleep -s 3
     $obj.SendKeys("7{ENTER}")
     sleep -s 3
     $obj.SendKeys("1{ENTER}")
     sleep -s 3
     $obj.SendKeys("{ENTER}")
     sleep -s 3
     $obj.SendKeys("{ENTER}")
     sleep -s 3
     $obj.SendKeys("Y{ENTER}")
     sleep -s 3
     $obj.SendKeys("{ENTER}")
     sleep -s 3
     }

答案4

这是一个运行 SendKeys 并在完成后清理 COM 对象的函数。它并不完美,但它可以工作。

-Delay 参数让您有时间在发送键之前将焦点切换到另一个应用程序。

function Send-Keystrokes ([string] $Keys, [int] $Delay = 0)
{
    try
    {
        Start-Sleep -Seconds $Delay
        $wshell = New-Object -ComObject WScript.Shell
        $wshell.SendKeys($Keys)
        Start-Sleep -Seconds 1
    }
    finally
    {
        try
        {
            [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$wshell) | Out-Null
            [System.GC]::Collect()
            [System.GC]::WaitForPendingFinalizers()
        }
        catch { }
    }
}

相关内容