【问题标题】:What can I query to see if Windows is booted and done with updates?我可以查询什么来查看 Windows 是否已启动并完成更新?
【发布时间】:2019-08-04 22:19:27
【问题描述】:

我的目标是远程检查一组计算机(详细列表),不仅要查看服务器是否已重新启动(通常是上次重新启动时),还要查看 Windows 是否已完全启动并在登录屏幕上运行,并且不会重新启动以进行进一步更新或仍在安装更新。

我确实找到了一个名为 AppReadiness 的服务,它在服务器重新启动之前停止了它。我担心如果它设置为手动,它可能不会总是启动。有人可以确认这是一项可靠的服务吗?

编辑:在我写这篇文章的时候,我确实发现它已经停止了,直到它显示“正在进行更新,100% 完成,不要关闭你的计算机”,但是当服务器挂在该消息上时, AppReadiness 服务已启动。有什么更好看的吗?我已经阅读了关于不同问题的其他答案,比如检查 C$ 是否可用,但它比 AppReadiness 可用更早。

用于检查服务的代码:

$creds = Get-Credential -Message "Enter server credentials:" -UserName "SERVERNAME\Administrator"
Get-WmiObject Win32_Service -ComputerName "SERVERIPADDRESS" -Credential $creds | Where-Object {$_.Name -eq "AppReadiness"}

编辑 2:此外,除了监视服务之外,我还尝试寻找 winlogon.exe 和 loginui.exe 等进程以获取有关服务器状况的指导,但我没有收到我想要记录的结果。这些进程显示服务器何时准备就绪,而我希望它们只会在登录 GUI 可见时显示。

编辑 3:

此编辑是针对 @Kelv.Gonzales 的回答,他声明要检查 Windows 事件日志“DHCPv4 客户端服务已启动”日志条目。这不起作用,并且与我监控的其他服务和事件相当。它在登录屏幕之前显示有效。

我的代码是:

$creds = Get-Credential -Message "Enter server credentials:" -UserName "SERVERNAME\Administrator"
$server = "IPADDRESSOFSERVER"

while($true)
{
    $event = Get-WmiObject Win32_NTLogEvent -ComputerName $server -Credential $creds -Filter "(logfile='System' AND eventcode = '50036')" | select -First 1
    $event.ConvertToDateTime($event.TimeWritten)
    Start-Sleep -Seconds 5
}

【问题讨论】:

  • 你试过什么?您的代码在哪里并向我们展示您遇到的错误。您可以使用一个简单的服务观察器,当它们运行时,它会向您发送警报、电子邮件或文本。
  • 代码不多,因为我是通过 PowerShell 使用 WMI 来获取 Windows 服务的状态,这也导致没有错误。问题是找到一个在登录屏幕之前没有启动的服务。对于这个项目,我不能修改目标服务器,只能查询它。我已经用我用来检查服务的单行 PowerShell 代码更新了我的问题。

标签: windows powershell wmi


【解决方案1】:

当然,那一艘班轮只会发射一次。为什么你使用 WMI,而不是内置的 PowerShell cmdlet - Get-Service

我的建议是使用 WMI 事件观察器,使用您已有的,但以服务和任何依赖服务为目标,并让该事件在状态运行时通知您。

Use PowerShell to Monitor and Respond to Events on Your Server

本文使用 PowerShell 和 VBScript 执行此操作,但您可以使用所有 PowerShell 执行此操作。

你可以有一个临时或永久的观察者。

PowerShell and Events: WMI Temporary Event Subscriptions

这些可能会有点深,因此,如果它们不适合您,您可以在服务上线后停止的 Do Loop 中使用您的一行。

基本示例:

$TargetHost = $env:COMPUTERNAME
do {
    $TargetOperation = Get-WmiObject Win32_Service -ComputerName $TargetHost  | 
    Where-Object {$_.Name -eq "AppReadiness"}
    "Checking host $TargetHost for service/process $($TargetOperation.Name)"
    Start-Sleep -Seconds 3
} until (($TargetOperation).State -eq 'Running')
"Validation of host $TargetHost for service/process $($TargetOperation.Name) complete"

# Results

Checking host WS70 for service/process AppReadiness
Checking host WS70 for service/process AppReadiness
Checking host WS70 for service/process AppReadiness
Validation of host WS70 for service/process AppReadiness complete

您当然可以使用操作逻辑添加任意数量的服务或流程。

以上所有内容几乎适用于您想观看的任何内容。服务、进程、文件夹。

或者只是在循环中使用这个脚本。

Get Remote Logon Status - Powershell

此脚本将返回本地或远程的登录状态 机器。返回类型包括“未登录”、“锁定”、“已登录” 开”和“离线。

这其中最有用的部分是检查计算机是否在 锁定状态,尽管其他返回类型也可能有用。

这是一个简单的功能,可以很容易地包含在一个更大的 脚本。返回类型可以更改为调用的数字 脚本更容易解析返回值。

下载:GetRemoteLogonStatus.ps1

【讨论】:

  • 谢谢。我使用 WMI,因为我需要将凭据传递给目标服务器,因为这些服务器都不在运行脚本的同一域中。我也猜想这可能不是正确的网站,因为我正在寻找比 AppReadiness 更好的东西,因为它在登录屏幕准备好之前(有时是几分钟)就开始了。
【解决方案2】:

找到 0 个排队的更新会满足您的需要吗?这个arcticle 详细介绍了如何完成它。

要检查 windows 是否已准备好登录,您能否查询“DHCPv4 客户端服务已启动”的事件日志 - 如果 windows 已准备好,则满足事件 ID 50036。

【讨论】:

  • 见编辑第三。不幸的是,这不起作用。
  • 嗯,我明白了。你能检查一下 Windows Modules Installer 是否没有运行吗?如果是,则可能意味着它仍在更新,因为这是手动启动。似乎是由 TrustedInstaller 触发的。
【解决方案3】:

我花了一周的时间寻找解决此问题的方法。我想分享一下我目前最好的解决方案,希望它对某人有所帮助。

@kelv-gonzales 对Windows Modules InstallerTrustedInstaller 的评论为我指明了正确的方向。

我的解决方案分解

存在一个名为 TiWorker.exe 的进程,即 Windows 模块安装程序工作进程。这是负责实际安装 Windows 更新的过程。这个过程(据我观察)在安装 Windows 更新的整个过程中可靠地运行。安装更新并需要等待重新启动后,此过程将停止并消失。

当您重新启动机器以满足等待重新启动时,TiWorker.exe 进程是在机器恢复时最先启动的进程之一。在某些情况下,根据更新的性质,将在计算机恢复时完成更新的安装(这是您在启动期间看到的不断增加的百分比)。一旦登录屏幕可用,这个过程通常会持续运行大约 2 分钟(根据我的观察)。之后,它停止并消失。我发现等待这几分钟是为了可靠地知道更新何时完成处理而付出的很小的代价。

我的脚本逻辑

我能够编写一个脚本来关闭该服务的存在。例如,下面是我的脚本的高级流程。

  1. 开始安装 Windows 更新。
  2. 等待更新以完成安装并等待重新启动。
  3. 一旦存在挂起的重新启动,请等待 TiWorker.exe 不再运行,然后触发重新启动。
  4. 当机器重新启动时,在重新启动期间反复检查机器的状态。当机器重新启动时,TiWorker.exe 将开始备份以完成更新。继续等待,直到 TiWorker.exe 不再运行(通常,更新将完成,操作系统将在锁定屏幕上等待大约 2 分钟,然后此过程才会停止)。

代码

我修改了@gabriel-graves 发布的代码以检查TiWorker.exe 进程。

$creds = Get-Credential -Message "Enter server credentials:" -UserName "SERVERNAME\Administrator"
Get-WmiObject Win32_Process -ComputerName "SERVERIPADDRESS" -Credential $creds | Where-Object {$_.Name -eq "TiWorker.exe"}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 2022-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-18
    • 1970-01-01
    相关资源
    最近更新 更多