我有用于自动 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。
- 通过 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 方法可能不可靠,但幸运的是,有更好的方法。
- 通过 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 { }
}
}