简体   繁体   English

有没有办法使用 C# 访问上次安装 Windows 更新的日期?

[英]Is there a way to access the date of the last installed Windows update using C#?

I'm working on adapting part of a powershell script to a WPF C# windows service and I'm having trouble finding a way to get the last installed windows update like the following script does.我正在努力将 powershell 脚本的一部分改编为 WPF C# windows 服务,但我无法找到一种方法来获取最后安装的 windows 更新,就像下面的脚本一样。 I need a way to check that a workstation has installed windows updates in the last 30 days, if it has it passes the audit if not it fails the audit.我需要一种方法来检查工作站是否在过去 30 天内安装了 Windows 更新,如果它通过了审核,如果不是,它没有通过审核。

$today = Get-Date   
$session = (New-Object -ComObject 'Microsoft.Update.Session')
$lastUpdate = ($session.QueryHistory("",0,100) | Where-Object 
{$_.ResultCode -eq 2}).Date | Sort-Object -descending
$compInfo = Get-ComputerInfo | select WindowsProductName, WindowsVersion
$OSversion = ($compInfo.WindowsProductName + " " + $compInfo.WindowsVersion).replace("Windows ","")

if (!$lastUpdate) {
    $never = $true
    $lastUpdate = Get-Date -Year 0001 -Month 01 -Day 01 -Hour 00 -Minute 00 -Second 00
} else {
    # Convert from UTC to timezone
    $timediff = [int]((Get-Timezone | select BaseUtcOffset | Out-String -Stream)[3][2].ToString())
    $lastUpdate = $lastUpdate[0].AddHours(-$timediff)
}

# Audit result
if ($never -or [datetime]$lastUpdate -le ($today.AddDays(-30))) {
    # Audit fail
    $pass = $false
    if ($never) {
        $lastUpdate = "Never"
    } else {
        $lastUpdate = [string]$lastUpdate
    }
} else {
    # Audit pass
}

I've been reading about the WUApi, but have not been able to get any variation of the following code to not produce errors when trying to use the IUpdateSearcher class.我一直在阅读有关 WUApi 的信息,但在尝试使用 IUpdateSearcher 类时无法获得以下代码的任何变体以不产生错误。 I've tried different namespaces an such and still haven't had any luck.我已经尝试过不同的命名空间,但仍然没有任何运气。

using WUApiLib;

UpdateSessionClass uSession = new UpdateSessionClass();
IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
ISearchResult uResult = uSearcher.Search("IsInstalled=0 and Type='Software'");

It doesn't seem like I will be able to replicate the powershell version exactly, but from what I've researched on the WUAPI I could just check if the computer has any updates that haven't been installed and assign a pass if there are no updates and fail if there are.似乎我无法准确复制 powershell 版本,但是根据我对 WUAPI 的研究,我可以检查计算机是否有任何尚未安装的更新,如果有则分配一个通行证没有更新,如果有则失败。

As explained here , you could compile a file summarizing the updates.正如这里所解释的,您可以编译一个总结更新的文件。

By default, it is written to your desktop:默认情况下,它会写入您的桌面:

"%USERPROFILE%\Desktop\WindowsUpdate.log"

This operation can be started as sub-process of your skript or program.此操作可以作为脚本或程序的子进程启动。 It does not require admininstrative privileges.它不需要管理权限。

You can then read the file up to something like the following:然后,您可以将文件读取到如下内容:

2022.07.06 16:56:05.5197996 3936  8528  UDP               Title = Security Intelligence-Update f??r Microsoft Defender Antivirus - KB2267602 (Version 1.369.880.0)
2022.07.06 16:56:05.5198024 3936  8528  UDP               UpdateId = B701392C-6DF8-4D94-A07F-35D06C5014E7.200

The Title lines contain datei/time and KB number of the updates in chronological order. Title行按时间顺序包含更新的日期/时间和KB数。

In comments, you mentioned these (compile-time) errors:在评论中,您提到了这些(编译时)错误:

The type or namespace name 'UpdateSessionClass' could not be found (are you missing a using directive or an assembly reference?)找不到类型或命名空间名称“UpdateSessionClass”(您是否缺少 using 指令或程序集引用?)
The type or namespace name 'IUpdateSearcher' could not be found (are you missing a using directive or an assembly reference?)找不到类型或命名空间名称“IUpdateSearcher”(您是否缺少 using 指令或程序集引用?)

Apparently, something was wrong with your reference to WUApi.dll.显然,您对 WUApi.dll 的引用有问题。 This should work:这应该有效:

  1. In the solution explorer, directly below the project name, right-click on Dependencies.在解决方案资源管理器中,在项目名称正下方,右键单击依赖项。 A context menu appears.出现一个上下文菜单。
  2. From the context menu, select "Add COM Reference..." The "Reference Manager" dialog appears.从上下文菜单中,选择“添加 COM 引用...” 出现“引用管理器”对话框。
  3. In the dialog, on tab COM, scroll down and check "WUAPI 2.0 Type Library".在对话框中的 COM 选项卡上,向下滚动并选中“WUAPI 2.0 类型库”。 Click OK.单击确定。

Now you can query the update history, just like you did in the PowerShell script.现在您可以查询更新历史记录,就像您在 PowerShell 脚本中所做的一样。

using WUApiLib;

IUpdateSession3 session = new UpdateSession();
IUpdateHistoryEntryCollection history = session.QueryHistory("", 0, 1);
if (history.Count > 0)
{
    Console.WriteLine($"Latest Windows update was on {history[0].Date}.");
}
else
{
    Console.WriteLine("Not a single Windows update found.");
}

Notice I am not sorting history myself.请注意,我自己并没有对历史进行排序。 From the documentation (emphasis mine):文档(强调我的):

[out] retval A pointer to an IUpdateHistoryEntryCollection interface that contains the matching event records on the computer in descending chronological order. [out] retval指向IUpdateHistoryEntryCollection接口的指针,该接口包含计算机上按时间降序排列的匹配事件记录。

In other words, the top row is the latest update.换句话说,第一行是最新的更新。 Hence these parameters when calling IUpdateSession3::QueryHistory :因此调用IUpdateSession3::QueryHistory时的这些参数:

  • "" : no search criteria, just get me anything "" : 没有搜索条件,随便找我
  • 0 : start from the top 0 : 从顶部开始
  • 1 : give me (at most) one row 1 :给我(最多)一行

Please keep in mind that the history may yield updates that have been rolled back afterwards.请记住,历史记录可能会产生之后已回滚的更新。 I don't know how to fix this.我不知道如何解决这个问题。 But I assume your PowerShell script was having the same issue.但我认为您的 PowerShell 脚本也有同样的问题。

Kudos to the useful code sample in this post: https://stackoverflow.com/a/815525/2485966感谢这篇文章中有用的代码示例: https ://stackoverflow.com/a/815525/2485966

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM