SendKeys 不适用于后台任务
SendKeys doesn't work from background task
初始问题:
我在办公室使用外接键盘,所以我想打开 NumLock。但是当我在家时,我只使用笔记本电脑键盘,所以我得到的是数字而不是字母,我必须关闭 NumLock。
初步解决方案:
下面的脚本检测一个或两个键盘并根据需要打开或关闭 NumLock。
新问题:
这在命令行中完美运行,但我希望它在我登录时触发并自动发生。当我在后台从 Task Scheduler 运行 它时,此行不起作用:
Shell.SendKeys "{NUMLOCK}"
它会触发但不会切换锁定。没有错误报告。
更新:如果我在我的帐户 "only when user is logged on" 下将它安排到 运行,那么它可以工作,但显示 cmd window。如果我 运行 它在我的帐户下或在 "whether user is logged in or not" 的 SYSTEM 帐户下, window 会很好地消失,但它不起作用。
无论是来自 cmd 还是 运行 作为计划任务,我都会在它应该切换锁定时得到此输出:
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.
Found HID Keyboard Device
Found HID Keyboard Device
numLock is OFF
Toggling Numlock
所以脚本本身运行正常。
UPDATE2:看起来这可能与当 运行ning 作为后台任务时没有 windows 站点有关。结果 DetectNumlockConsole.exe
也不起作用。这是一个简单的 c# 应用程序,returns 这一行的结果
numLock = Control.IsKeyLocked(Keys.NumLock);
同样,这在 运行 "only when user is logged on" 而非 "whether user is logged in or not."
时有效
---------- vbs 脚本------------
set OUT = WScript.StdOut
Set Shell=CreateObject("Wscript.Shell")
Dim KeyCount
KeyCount = 0
Computer = "."
'set NumLock = CheckState
Set WMIService = GetObject("winmgmts:\" & Computer & "\root\cimv2")
Set Devices = WMIService.ExecQuery ("Select * From Win32_USBControllerDevice")
For Each Device in Devices
DeviceName = Device.Dependent
Quotes = Chr(34)
DeviceName = Replace(DeviceName, Quotes, "")
DeviceNames = Split(DeviceName, "=")
DeviceName = DeviceNames(1)
Set USBDevices = WMIService.ExecQuery ("Select * From Win32_PnPEntity Where DeviceID = '" & DeviceName & "'")
For Each USBDevice in USBDevices
'OUT.WriteLine USBDevice.Description ' Write description to command line to see what to look for
If InStr( LCase( USBDevice.Description ), "keyboard" ) <> 0 Then
KeyCount = KeyCount + 1
OUT.WriteLine "Found " & USBDevice.Description
End If
Next
Next
dim numLock
numLock = Shell.Run("DetectNumlockConsole.exe",0,True)
If (numLock = 0) Then
OUT.WriteLine "numLock is OFF"
Else
OUT.WriteLine "numLock is ON"
End If
' If we have a keyboard, and numlock is OFF
' Or we don't have a keyboard, and numlock is ON
' Then toggle it
If (((KeyCount > 1) AND (numLock = 0)) OR ((KeyCount = 1) AND (numLock = 1))) Then
Shell.SendKeys "{NUMLOCK}" ' *** Problem here, doesn't toggle **
OUT.WriteLine "Toggling Numlock"
End If
这就是 windows 安全工作的方式。它与 sendkeys 本身无关,但不同安全上下文下的任务不会影响其他任务。
如您所见,当 运行 在与 相同的安全上下文中时,只有 运行 当用户登录 时才有效。
这叫做进程隔离,主要是为了 安全和 UI 原则,没有人可以扰乱交互式用户。
初始问题:
我在办公室使用外接键盘,所以我想打开 NumLock。但是当我在家时,我只使用笔记本电脑键盘,所以我得到的是数字而不是字母,我必须关闭 NumLock。
初步解决方案: 下面的脚本检测一个或两个键盘并根据需要打开或关闭 NumLock。
新问题:
这在命令行中完美运行,但我希望它在我登录时触发并自动发生。当我在后台从 Task Scheduler 运行 它时,此行不起作用:
Shell.SendKeys "{NUMLOCK}"
它会触发但不会切换锁定。没有错误报告。
更新:如果我在我的帐户 "only when user is logged on" 下将它安排到 运行,那么它可以工作,但显示 cmd window。如果我 运行 它在我的帐户下或在 "whether user is logged in or not" 的 SYSTEM 帐户下, window 会很好地消失,但它不起作用。
无论是来自 cmd 还是 运行 作为计划任务,我都会在它应该切换锁定时得到此输出:
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.
Found HID Keyboard Device
Found HID Keyboard Device
numLock is OFF
Toggling Numlock
所以脚本本身运行正常。
UPDATE2:看起来这可能与当 运行ning 作为后台任务时没有 windows 站点有关。结果 DetectNumlockConsole.exe
也不起作用。这是一个简单的 c# 应用程序,returns 这一行的结果
numLock = Control.IsKeyLocked(Keys.NumLock);
同样,这在 运行 "only when user is logged on" 而非 "whether user is logged in or not."
时有效
---------- vbs 脚本------------
set OUT = WScript.StdOut
Set Shell=CreateObject("Wscript.Shell")
Dim KeyCount
KeyCount = 0
Computer = "."
'set NumLock = CheckState
Set WMIService = GetObject("winmgmts:\" & Computer & "\root\cimv2")
Set Devices = WMIService.ExecQuery ("Select * From Win32_USBControllerDevice")
For Each Device in Devices
DeviceName = Device.Dependent
Quotes = Chr(34)
DeviceName = Replace(DeviceName, Quotes, "")
DeviceNames = Split(DeviceName, "=")
DeviceName = DeviceNames(1)
Set USBDevices = WMIService.ExecQuery ("Select * From Win32_PnPEntity Where DeviceID = '" & DeviceName & "'")
For Each USBDevice in USBDevices
'OUT.WriteLine USBDevice.Description ' Write description to command line to see what to look for
If InStr( LCase( USBDevice.Description ), "keyboard" ) <> 0 Then
KeyCount = KeyCount + 1
OUT.WriteLine "Found " & USBDevice.Description
End If
Next
Next
dim numLock
numLock = Shell.Run("DetectNumlockConsole.exe",0,True)
If (numLock = 0) Then
OUT.WriteLine "numLock is OFF"
Else
OUT.WriteLine "numLock is ON"
End If
' If we have a keyboard, and numlock is OFF
' Or we don't have a keyboard, and numlock is ON
' Then toggle it
If (((KeyCount > 1) AND (numLock = 0)) OR ((KeyCount = 1) AND (numLock = 1))) Then
Shell.SendKeys "{NUMLOCK}" ' *** Problem here, doesn't toggle **
OUT.WriteLine "Toggling Numlock"
End If
这就是 windows 安全工作的方式。它与 sendkeys 本身无关,但不同安全上下文下的任务不会影响其他任务。
如您所见,当 运行 在与 相同的安全上下文中时,只有 运行 当用户登录 时才有效。
这叫做进程隔离,主要是为了 安全和 UI 原则,没有人可以扰乱交互式用户。