从终端,我如何确定 Windows 上次锁定或解锁的日期/时间?

从终端,我如何确定 Windows 上次锁定或解锁的日期/时间?

为了基本的安全,每次我离开电脑时都会按WinKey+ L。当我回来时,我会输入简短的 Windows 密码,然后按 Enter 返回我的桌面。(这不是“注销”或“登录”。)

现在,我试图通过终端命令确定机器上次以这种方式锁定或上次解锁的时间戳。哪一个都不重要;两者对我来说同样重要。

(它将用于确定何时向我的安全系统发送“生命信号”。)

Windows 10 Pro。请不要使用外部软件。如果可能的话,我会更喜欢如果解决方案也不使用 PowerShell,因为该环境存在许多难以解释的问题。

理想的答案应该是这样的:

getlastunlock.exe

打印内容:

2020-11-17 01:07:04

请告诉我 Windows 中是否有这样的功能。

答案1

这可以通过处理wevtutil西窗口埃夫英文 实用工具权限 (ity) 命令。在继续之前,我同意 Ramhound 的观点,即 PowerShell 是实现此目的的更好方法。

有四个事件 ID 可能与您相关:

  • 7001 是登录事件
  • 7002 是注销事件
  • 4800 是锁定事件
  • 4801 是解锁事件

下面是一个 Windows您可以从命令行运行它。您可以命名它getlastunlock.bat并将其保存在您的PATH变量。然后您可以打开命令提示符并运行getlastunlock以查看结果。

批处理文件

@ECHO off
FOR /F "usebackq tokens=16 delims=^<" %%a IN (`wevtutil qe System /rd ^| findstr "4800 4801"`) DO (
   CALL:getTime "%%a"
   GOTO:EndLoop
)
:EndLoop
EXIT /b

:getTime
SETLOCAL
:: getTime String [RtnVar]
::             -- String  The string to pull the time from.
::             -- RtnVar  An optional variable to be used to return the time.
SET "s=%~1"
SET "tTime=%s:~24,19%"
SET "time=%tTime:T= %"
ENDLOCAL&IF "%~2" neq "" (set %~2=%time%) ELSE ECHO %time%
EXIT /b

分解

以下是此脚本的具体操作:

  1. @ECHO off告诉批处理解释器不显示正在运行的命令。默认情况下,您将看到与您自己输入的命令完全相同的命令。
  2. FOR /F "usebackq tokens=16 delims=^<" %%a IN (wevtutil qe System ^| findstr "7001 4801" 这个词) DO (听起来有点拗口,我们进一步分解一下:
    1. FOR /F是一个循环命令。它接受一些输入并循环遍历其中的每一行。
    2. usebackq使用输入的替代引用样式,使得传递包含引号的命令变得更容易。
    3. tokens=16意味着我们只想要该行中的第 16 个项目。
    4. delims=^<表示我们希望根据<字符将每行拆分为单独的项目。的输出wevutil为 XML 格式,用于<elements>存储信息。wevutil也允许以文本形式输出,但解析起来会比较困难。
    5. %%a定义该行第16项的变量名,以便后面使用。
    6. IN意思是“使用以下命令让输出循环通过。
    7. (`wevtutil qe System /rd ^| findstr "4800 4801"`)是返回我们想要循环的输出的命令。
      1. wevtutil qe System /rd意味着我们要System以相反的时间顺序(最新的在前)导出事件日志的内容。
      2. ^|是转义的“管道符”。也就是说, 的输出wevtutil将被“管道化”或用作下一个命令的输入。我们|用 字符“转义”该^字符,以告诉批处理解释器不要使用 来|拆分整行,而只使用这两个命令。
      3. findstr "4800 4801"获取输出wevtutil并搜索包含4800和的行4801,即我们的锁定和解锁事件。您可以将其更改为您想要的任何事件 ID。
    8. DO表示在输出的每一行上运行以下命令。
  3. CALL:getTime "%%a"将当前行的第 16 项发送给getTime子程序。
  4. GOTO:EndLoop退出循环,以便它只运行一次,这意味着它将只处理最近的相关结果。GOTO不同于CALL因为当子程序结束时,脚本也结束。如果是CALL,那么子程序结束将使脚本返回到此行之后的行。
  5. :EndLoop定义一个我们可以调用的标签GOTO
  6. EXIT /b告诉命令解释器在此退出批处理文件。此行之后的所有内容都应是从上述代码中调用的子程序。
  7. :getTime定义子程序的名称。
  8. SETLOCAL定义一个本地上下文,这意味着在此上下文中设置的任何环境变量都不会传回批处理文件的其余部分。
  9. SET "s=%~1"将子程序的输入设置到s变量中。
  10. SET "tTime=%s:~24,19%"以 T 为界,ISO 8601来自变量的格式化时间s
  11. SET "time=%tTime:T= %"用空格替换 T 以获得您想要的格式。
  12. ENDLOCAL&IF "%~2" neq "" (set %~2=%time%) ELSE ECHO %time%利用命令解释器的全行处理来结束本地上下文从中传递一个变量(时间)。
  13. EXIT /b这里告诉命令解释器子程序已经结束,并返回到原来的位置进行处理。

参考

相关内容