Hallo SRE,
Hier ist die genaue Vorgehensweise und Syntax, um diese Anforderungen asynchron abzufragen und die Zustände sauber zu trennen.
- Voraussetzung: COM-Referenz hinzufügen
Bevor Sie den Code ausführen können, müssen Sie eine Referenz auf die wuapi.dll (Windows Update Agent API) in Ihr Projekt einfügen:
In Visual Studio: Rechtsklick auf Abhängigkeiten/Verweise -> COM -> Suchen nach "WUAPI 2.0 Type Library" und hinzufügen.
- C#-Implementierung
Die WUA API bietet zwar eigene asynchrone Methoden (BeginSearch / EndSearch), in modernem C# ist es jedoch wesentlich sauberer und robuster, die synchronen Aufrufe in einen Task.Run zu kapseln, um die asynchrone Ausführung (async/await) zu gewährleisten, ohne den Hauptthread zu blockieren.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WUApiLib; // Namespace der COM-Referenz
public class UpdateStatusReport
{
public bool SystemRebootRequired { get; set; }
public List<string> ActiveOrPendingDownloads { get; set; } = new List<string>();
public List<string> WaitingForDeployment { get; set; } = new List<string>();
}
public class WindowsUpdateMonitor
{
/// <summary>
/// Fragt den Windows Update Agenten asynchron ab.
/// </summary>
public async Task<UpdateStatusReport> CheckUpdateLifecycleAsync()
{
return await Task.Run(() =>
{
var report = new UpdateStatusReport();
// Instanziiere die Update-Session
UpdateSession session = new UpdateSession();
// --- 1. NEUSTART-STATUS PRÜFEN ---
// Prüft, ob das System aufgrund eines vorherigen Updates einen Neustart benötigt
ISystemInformation sysInfo = session.CreateUpdateSystemInformation();
report.SystemRebootRequired = sysInfo.RebootRequired;
// --- 2. UPDATES SUCHEN ---
IUpdateSearcher searcher = session.CreateUpdateSearcher();
// Best Practice für Monitoring: Online = false fragt nur den lokalen WUA-Cache ab.
// Das ist wesentlich schneller und erzeugt keinen Netzwerktraffic.
// Setzen Sie es auf true, wenn Sie zwingend gegen den WSUS/Microsoft-Server prüfen wollen.
searcher.Online = false;
// Such-Syntax: Finde alle Updates, die nicht installiert und nicht versteckt sind.
ISearchResult searchResult = searcher.Search("IsInstalled=0 and IsHidden=0");
foreach (IUpdate update in searchResult.Updates)
{
// --- 3. ZUSTÄNDE DIFFERENZIEREN ---
if (update.IsDownloaded)
{
// Paket liegt fertig im SoftwareDistribution-Ordner und wartet auf die Installation
report.WaitingForDeployment.Add(update.Title);
}
else
{
// Paket ist bekannt, aber noch nicht (vollständig) lokal vorhanden.
report.ActiveOrPendingDownloads.Add(update.Title);
}
}
return report;
});
}
}
- Wichtige architektonische Details zur Unterscheidung
Pakete, die einen Neustart erfordern:
Sobald ein Update installiert ist und einen Neustart erfordert, verschwindet es aus der Suche IsInstalled=0. Daher ist es der sicherste und global gültige Weg, session.CreateUpdateSystemInformation().RebootRequired abzufragen. Dies deckt das gesamte Betriebssystem ab, nicht nur isolierte Update-Objekte.
Pakete, die auf Bereitstellung warten:
Dies wird über die Eigenschaft update.IsDownloaded == true (in Kombination mit der Suchabfrage IsInstalled=0) ermittelt. Das Paket liegt installationsbereit im Cache.