当用户解锁 Windows 机器时运行 Python 脚本

当用户解锁 Windows 机器时运行 Python 脚本

我有一个 python 脚本,我想在用户解锁机器时运行它;即当用户按下 Cntl-Alt-Delete 并输入用户名和密码并登录时。

我该怎么做? 是否有任何注册表值,我可以添加

pythonw.exe C:\myscript.py 这样,它每次都会运行 myscript.py,用户就可以解锁机器?

答案1

对于 Windows XP,使用 PyWin32 来:

  • win32gui.CreateWindow()看不见的窗户
  • 称呼win32ts.WTSRegisterSessionNotification()
  • 监听WM_WTSSESSION_CHANGE窗口消息wparam == WTS_SESSION_UNLOCK
    • 参数将是会话 ID
  • 下面包括一个示例实现。

如果你想让脚本工作多种的用户,将其转换为服务win32serviceutil对此很方便);请参阅wtsmonitor-svc.py上述地址。


示例程序

  1. 进行编辑events.py以满足您的需要。

  2. 对于单个用户,运行:

    wtsmonitor.pyw
    

    对于系统范围的服务,请运行:

    wtsmonitor-svc.py --startup auto install
    wtsmonitor-svc.py start
    sc query WTSMonitor
    

附件 1/3:wtsmonitor.pyw

#!python
# (c) 2011 Mantas Mikulėnas <[email protected]>
# Released under the MIT license <https://spdx.org/licenses/MIT>
from __future__ import print_function
import os
import sys
import subprocess

try:
    import win32api as api
    import win32con as con
    import win32gui as gui
    import win32ts as ts
except ImportError:
    print("wtsmonitor: PyWin32 modules not found", file=sys.stderr)
    sys.exit(1)

try:
    import events
except ImportError:
    print("wtsmonitor: events.py not found", file=sys.stderr)
    sys.exit(1)

# window messages
WM_WTSSESSION_CHANGE        = 0x2B1

# WM_WTSSESSION_CHANGE events (wparam)
WTS_CONSOLE_CONNECT     = 0x1
WTS_CONSOLE_DISCONNECT      = 0x2
WTS_REMOTE_CONNECT      = 0x3
WTS_REMOTE_DISCONNECT       = 0x4
WTS_SESSION_LOGON       = 0x5
WTS_SESSION_LOGOFF      = 0x6
WTS_SESSION_LOCK        = 0x7
WTS_SESSION_UNLOCK      = 0x8
WTS_SESSION_REMOTE_CONTROL  = 0x9

methods = {
    WTS_CONSOLE_CONNECT:        "ConsoleConnect",
    WTS_CONSOLE_DISCONNECT:     "ConsoleDisconnect",
    WTS_REMOTE_CONNECT:     "RemoteConnect",
    WTS_REMOTE_DISCONNECT:      "RemoteDisconnect",
    WTS_SESSION_LOGON:      "SessionLogon",
    WTS_SESSION_LOGOFF:     "SessionLogoff",
    WTS_SESSION_LOCK:       "SessionLock",
    WTS_SESSION_UNLOCK:     "SessionUnlock",
    WTS_SESSION_REMOTE_CONTROL: "SessionRemoteControl",
}

class WTSMonitor():
    className = "WTSMonitor"
    wndName = "WTS Event Monitor"

    def __init__(self, all_sessions=False):
        wc = gui.WNDCLASS()
        wc.hInstance = hInst = api.GetModuleHandle(None)
        wc.lpszClassName = self.className
        wc.lpfnWndProc = self.WndProc
        self.classAtom = gui.RegisterClass(wc)

        style = 0
        self.hWnd = gui.CreateWindow(self.classAtom, self.wndName,
            style, 0, 0, con.CW_USEDEFAULT, con.CW_USEDEFAULT,
            0, 0, hInst, None)
        gui.UpdateWindow(self.hWnd)

        if all_sessions:
            scope = ts.NOTIFY_FOR_ALL_SESSIONS
        else:
            scope = ts.NOTIFY_FOR_THIS_SESSION
        ts.WTSRegisterSessionNotification(self.hWnd, scope)

    def start(self):
        gui.PumpMessages()

    def stop(self):
        gui.PostQuitMessage(0)

    def WndProc(self, hWnd, message, wParam, lParam):
        if message == WM_WTSSESSION_CHANGE:
            self.OnSession(wParam, lParam)
        elif message == con.WM_CLOSE:
            gui.DestroyWindow(hWnd)
        elif message == con.WM_DESTROY:
            gui.PostQuitMessage(0)
        elif message == con.WM_QUERYENDSESSION:
            return True

    def OnSession(self, event, sessionID):
        name = methods.get(event, "unknown")
        print("event %s on session %d" % (
            methods.get(event, "unknown(0x%x)" % event), sessionID))

        try:
            method = getattr(events, name)
        except AttributeError:
            method = getattr(events, "default", lambda e, s: None)

        method(event, sessionID)

if __name__ == '__main__':
    m = WTSMonitor(all_sessions=True)
    m.start()

附件2/3:wtsmonitor-service.py

#!python
# (c) 2011 Mantas Mikulėnas <[email protected]>
# Released under the MIT license <https://spdx.org/licenses/MIT>
from __future__ import print_function

try:
    import win32service as svc
    import win32serviceutil as svcutil
except ImportError:
    print("wtsmonitor-svc: PyWin32 modules not found", file=sys.stderr)
    sys.exit(1)

import wtsmonitor

class WTSMonitorService(svcutil.ServiceFramework):
    _svc_name_ = "WTSMonitor"
    _svc_display_name_ = "Terminal Services event monitor"
    _svc_description_ = "Runs custom actions on Terminal Services session events."
    _svc_deps_ = ["TermService"]

    m = None

    def SvcStop(self):
        self.ReportServiceStatus(svc.SERVICE_STOP_PENDING)
        self.m.stop()
        self.ReportServiceStatus(svc.SERVICE_STOPPED)

    def SvcDoRun(self):
        self.m = wtsmonitor.WTSMonitor(all_sessions=True)
        self.m.start()

if __name__ == '__main__':
    svcutil.HandleCommandLine(WTSMonitorService)

附件 3/3:(events.py示例)

#!python
# See the 'methods' dict in wtsmonitor.pyw for a list of possible events.

def default(event, session):
    pass

def unknown(event, session):
    pass

def SessionLock(event, session):
    pass

答案2

您可以使用 Windows 任务计划程序(Vista 及更高版本)或计划任务控制面板(WinXP)创建触发“登录时”或“工作站解锁时”的计划任务。我相信这样的触发器将导致任务在您描述的场景中执行。

答案3

你应该检查任务管理器

使管理员能够在本地或远程计算机上创建、删除、查询、更改、运行和结束计划任务。运行不带参数的 Schtasks.exe 将显示每个已注册任务的状态和下次运行时间。

相关内容