我有一个 powershell 脚本:
$i = 0
$delay = 1000
while($i -eq 0)
{
$myshell = New-Object -com "Wscript.Shell"
$myshell.sendkeys("q")
Start-Sleep -m $delay
}
它可以工作,但我不想只发送片刻的按键,而是想模拟按下按键一会儿,例如 1 秒。
答案1
要使用 sendkeys 向任何对象发送多个击键,您只需执行以下操作(实际上不需要 WScript 的东西):
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait('q'*3)
# Results
<#
qqq
#>
如果您尝试根据时间状态执行此操作,则需要提供该状态。因此,这意味着设置秒表。
https://duckduckgo.com/?q=%27powershell+using+a+timer%27&t=h_&ia=web
带有表单的计时器的示例:
Add-Type -AssemblyName Microsoft.VisualBasic,
PresentationCore,
PresentationFramework,
System.Drawing,
System.Windows.Forms,
WindowsBase,
WindowsFormsIntegration
$delay = 10
$Counter_Form = New-Object System.Windows.Forms.Form
$Counter_Form.Text = "Countdown Timer!"
$Counter_Form.Width = 450
$Counter_Form.Height = 200
$Counter_Label = New-Object System.Windows.Forms.Label
$Counter_Label.AutoSize = $true
$Counter_Form.Controls.Add($Counter_Label)
while ($delay -ge 0)
{
$Counter_Form.Show()
$Counter_Label.Text = "Seconds Remaining: $($delay)"
start-sleep 1
$delay -= 1
}
$Counter_Form.Close()
使用计时器对象,一个简短的例子:
$Timer = New-Object system.diagnostics.stopwatch
$Timer.Start()
Start-Sleep -Milliseconds 1001
$Timer.Stop()
$timer
# Results
<#
IsRunning Elapsed ElapsedMilliseconds ElapsedTicks
--------- ------- ------------------- ------------
False 00:00:01.0055471 1005 10055471
#>
因此,您最终将使用上面的代码进行操作。
Add-Type -AssemblyName System.Windows.Forms
$Timer = New-Object system.diagnostics.stopwatch
$Timer.Start()
while ($Timer.ElapsedMilliseconds -le 1000)
{[System.Windows.Forms.SendKeys]::SendWait('q')}
# Results
<#
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
#>
使用延迟/睡眠
Add-Type -AssemblyName System.Windows.Forms
$Timer = New-Object system.diagnostics.stopwatch
$Timer.Start()
while ($Timer.ElapsedMilliseconds -le 1000)
{
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait('q')
}
# Results
<#
qqqqqqq
#>
根据SilBee's
评论更新:
对任何按键采取行动。
Add-Type -AssemblyName System.Windows.Forms
$Timer = New-Object system.diagnostics.stopwatch
$Timer.Start()
while ($Timer.ElapsedMilliseconds -le 1000)
{
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | OUT-NULL
[System.Windows.Forms.SendKeys]::SendWait('q')
Start-Sleep -Milliseconds 100
}
'Done'
$Timer
# Results
<#
Done
IsRunning Elapsed ElapsedMilliseconds ElapsedTicks
--------- ------- ------------------- ------------
True 00:00:02.0041171 2004 20041490
q
#>
如果您仅追求特定的键,那么 $Host 对象仍然会提供该键。
$Host.UI.RawUI.ReadKey()
# Results
<#
q
VirtualKeyCode Character ControlKeyState KeyDown
-------------- --------- --------------- -------
81 q NumLockOn True
#>
因此,您可以对特定字母进行编码,然后分支到您选择的任何其他代码。
举一个粗略的例子,可能是这样的:
Add-Type -AssemblyName System.Windows.Forms
$Timer = New-Object system.diagnostics.stopwatch
$Timer.Start()
while (($Host.UI.RawUI.ReadKey()).Character -eq 'q')
{
[System.Windows.Forms.SendKeys]::SendWait('q')
Start-Sleep -Milliseconds 100
If ($Timer.ElapsedMilliseconds -ge 5000)
{Break}
}
'Done'
$Timer
# Results
<#
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqDone
IsRunning Elapsed ElapsedMilliseconds ElapsedTicks
--------- ------- ------------------- ------------
True 00:00:05.0420154 5042 50420519
#>
再次强调,上面是用户触摸键盘,而不是模拟事件。
尝试模拟这种情况可能会/会导致 SendKeys 产生奇怪的结果/行为,而无需进行大量微调,也不需要潜在地调用 user32.dll。
必须记住,按下并按住是键盘设备的机械动作(通过键盘驱动程序向操作系统发出信号)。内存中没有这样的东西,所有代码都是在内存中触发的。