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 原则,没有人可以扰乱交互式用户。