如何在 powershell 脚本中按住一个键一秒钟?

如何在 powershell 脚本中按住一个键一秒钟?

我有一个 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。

必须记住,按下并按住是键盘设备的机械动作(通过键盘驱动程序向操作系统发出信号)。内存中没有这样的东西,所有代码都是在内存中触发的。

相关内容