bensonhedges
Goto Top

Powershell Datum der zuletzt eingespielten Patche bei remote Servern ermitteln

Hallo,

ich möchte gerne anhand einer Serverliste (bsp. computers.txt) via PS ermitteln,
wann derjeweilige Server zuletzt gepatcht wurde (Liste der installierten Patche sind nicht wichtig).

Wie bekomme ich das möglichst einfach mit Powershell-Mitteln hin?
Würde das Skript gerne mit privilegierten Rechten starten (Domänen-Admin), wie bekomme ich das ins Skript eingebaut?

Danke für Eure Tipps!

Gruß,
der Benson

Content-ID: 453762

Url: https://administrator.de/contentid/453762

Ausgedruckt am: 22.11.2024 um 12:11 Uhr

Pjordorf
Pjordorf 20.05.2019 um 13:07:47 Uhr
Goto Top
Hallo,

Zitat von @bensonhedges:
wann derjeweilige Server zuletzt gepatcht wurde (Liste der installierten Patche sind nicht wichtig).
Das wird dir nicht zwingend weiterhelfen, aber wenn eine Maschine 6 Monate in der Ecke stand und sich jetzt ein Patch ausm letzten Jahr zog, ohne das du weisste welches Update es war, kannst du nur davon ausgehen das der Rechner Kontakt mit seinen Elter hatte.

Gruß,
Peter
bensonhedges
bensonhedges 20.05.2019 um 13:17:06 Uhr
Goto Top
Stimmt, da hast Du recht. Dann wäre es sinnvoll, per Skript zu ermitteln, welches das letzte erfolgreich installierte Update war.
Pjordorf
Pjordorf 20.05.2019 um 13:21:26 Uhr
Goto Top
Hallo,

Zitat von @bensonhedges:
Stimmt, da hast Du recht. Dann wäre es sinnvoll, per Skript zu ermitteln, welches das letzte erfolgreich installierte Update war.
https://community.spiceworks.com/topic/1965305-get-windows-updates-last- ...

Gruß,
Peter
bensonhedges
bensonhedges 20.05.2019 um 13:41:46 Uhr
Goto Top
Hi Peter,

das Skript pass schon ganz gut, allerdings gibt es Probleme bei dem deutschen Datum, das wird nicht
korrekt angezeigt (Monat/Tag vertauscht):

sort : Ausnahme beim Abrufen von "InstalledOn": "Ausnahme beim Aufrufen von "Parse" mit 1 Argument(en): "Die Zeichenfolge wurde nicht als gültiges DateTime erkannt.""
In Zeile:1 Zeichen:125

back-to-top... putername $_ | sort installedon)[-1] } >> C:\temp\file.txt

back-to-top~~~~~~~~~~~~~~~~

bensonhedges
bensonhedges 20.05.2019 um 13:42:30 Uhr
Goto Top
Das Skript sieht aktuell so aus:

Get-Content c:\temp\computers.txt  | Where {$_ -AND (Test-Connection $_ -Quiet)} | foreach { (Get-Hotfix -computername $_ | sort installedon)[-1] } >> C:\temp\file.txt
Spanish
Spanish 20.05.2019 um 13:52:13 Uhr
Goto Top
Hola,

Zitat von @bensonhedges:
Das Skript sieht aktuell so aus:
Lass doch mal das InstalledOn ganz weg. Es gibt auch Updates die keinerlei Datum haben.

Besten Gruß,
Spanish
bensonhedges
bensonhedges 20.05.2019 um 13:55:07 Uhr
Goto Top
Hallo Spanish,

das bringt mir leider nichts, da ich ermitteln möchte, _wann_ das letzte Update auf dem jeweiligen Server
installiert worden ist.

BG,
Benson
Spanish
Spanish 20.05.2019 um 13:58:39 Uhr
Goto Top
Hola,

Zitat von @bensonhedges:
das bringt mir leider nichts, da ich ermitteln möchte, _wann_ das letzte Update auf dem jeweiligen Server
Ich meinte ja auch nur weil du unter anderem
sort : Ausnahme beim Abrufen von "InstalledOn": "Ausnahme beim Aufrufen von "Parse" mit 1 Argument(en): "Die Zeichenfolge wurde nicht als gültiges DateTime erkannt.""
In Zeile:1 Zeichen:125
bekommst. Ich bin aber nicht der Powershellexperte.

Besten Gruß,
Spanish
bensonhedges
bensonhedges 20.05.2019 um 14:05:22 Uhr
Goto Top
Hi Peter,

danke, den Link, kenne ich ja schon, aber da steht leider nicht die Lösung zum Problem.
Das Datum wird einfach nicht korrekt ausgegeben. Ansonsten reicht die Ausgabe aus.

Gruß,
benson
bensonhedges
bensonhedges 20.05.2019 um 14:28:58 Uhr
Goto Top
Dies könnte die Lösung sein:

http://joekadev.de/powershell-abfrage-der-letzten-windows-update-instal ...

Dort wird das Datum auch korrekt ausgegeben.
Da ich in PS nicht fit bin, wie kann ich eine Schleife drumrum bauen, damit eine .txt eingelesen wird und
alle die Server einzeln geprüft werden?

Hier das Skript von joekadev.de :

    # Letzte erfolgreiche Installation eines Windows Updates ueberpruefen
    # www.joekadev.de
    $computer = "hostname-hier"  #Lokaler/Remote Computername  
    Function LWUCheck {
            $key = “SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install” 
            $keytype = [Microsoft.Win32.RegistryHive]::LocalMachine 
            $RemoteBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype,$computer) 
            $regKey = $RemoteBase.OpenSubKey($key) 
            $KeyValue = $regkey.GetValue(”LastSuccessTime”) 
            $System = (Get-Date -Format "yyyy-MM-dd hh:mm:ss")    
            if ($KeyValue -lt $System) 
            { 
                Write-Host $computer " - " $KeyValue  
            }
    }
    LWuCheck > D:\scripte\lwucheck.txt
SaschaRD
SaschaRD 20.05.2019 aktualisiert um 15:02:16 Uhr
Goto Top
Hallo,
gc c:\temp\computers.txt | ?{$_ -AND (Test-Connection $_ -Quiet)} | %{(Get-Hotfix -computername $_ | Sort InstalledOn -Descending)} >> C:\temp\file.txt

Ansonsten hilft auch Meister Google-Hupf face-smile

Nur das Datum:
(Get-Hotfix | Sort InstalledOn -Descending).InstalledOn

Gruß, Sascha
bensonhedges
bensonhedges 20.05.2019 um 15:39:36 Uhr
Goto Top
Hi Sascha,

danke Dir! Ich hatte ein anderes Skript gemeint, das würde mir ausreichen, nur da bekomme ich die Schleife nicht herumgebastelt face-smile

Dieses meine ich, wo ich gerne ein .txt-File einlesen möchte:

    # Letzte erfolgreiche Installation eines Windows Updates ueberpruefen
    # www.joekadev.de
    $computer = "hostname-hier"  #Lokaler/Remote Computername  
    Function LWUCheck {
            $key = “SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install” 
            $keytype = [Microsoft.Win32.RegistryHive]::LocalMachine 
            $RemoteBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype,$computer) 
            $regKey = $RemoteBase.OpenSubKey($key) 
            $KeyValue = $regkey.GetValue(”LastSuccessTime”) 
            $System = (Get-Date -Format "yyyy-MM-dd hh:mm:ss")    
            if ($KeyValue -lt $System) 
            { 
                Write-Host $computer " - " $KeyValue  
            }
    }
    LWuCheck > D:\scripte\lwucheck.txt

Gruß,
Benson
SaschaRD
SaschaRD 21.05.2019 um 09:33:20 Uhr
Goto Top
Hallo @bensonhedges

das Einlesen von Dateien ist über Get-Content (kurz gc) möglich.
$computers = gc D:\temp\hostname.txt

foreach ($computer in $computers){
    $key = “SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install” 
    $keytype = [Microsoft.Win32.RegistryHive]::LocalMachine 
    $RemoteBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype,$computer) 
    $regKey = $RemoteBase.OpenSubKey($key) 
    $KeyValue = $regkey.GetValue(”LastSuccessTime”) 
    $System = (Get-Date -Format "yyyy-MM-dd hh:mm:ss")    
    if ($KeyValue -lt $System) 
    { 
        Write-Host $computer " - " $KeyValue  
    }
}
Dann wird das Ganze noch etwas umgestellt (Function entfernt) und mit einem hübschen Schleifchen drum herum versehen und schon initiiert diese über alle Computernamen welche sich in der Textdatei befinden.

Gruß, Sascha
138959
138959 21.05.2019 um 11:02:46 Uhr
Goto Top
Ich kann dir hier nur zur einer Inventarisierungslösung wie lansweeper raten.
Damit bekommt ihr alle Maschinen auch wirklich in den Report. Mit SQL könnt ihr euch
Custom Reports bauen. Hab dazu mal was zu Windows updates geschrieben:

Vielleicht macht es dir das leichter.
https://www.protoncode.de/lansweeper-report-windows-updates/

Nein, ich bekomme von Lansweeper keine Provision ^^
bensonhedges
bensonhedges 23.05.2019 um 11:54:34 Uhr
Goto Top
Hallo Sascha,

vielen Dank für das Schleifchen face-smile

Bei mir kommt aber leider ein Fehler:

Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
In Zeile:8 Zeichen:5

back-to-top$KeyValue = $regkey.GetValue(”LastSuccessTime”)

back-to-top~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ CategoryInfo : InvalidOperation: (face-smile , RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

pc0001 -
---

Hast Du eine Idee, was das sein kann. In der Hostname.txt steht ein Eintrag (pc0001).

Gruß,
benson
bensonhedges
bensonhedges 03.06.2019 um 12:37:44 Uhr
Goto Top
Kann mir jemand bei der Fehlereingrenzung helfen? Bin leider nicht so fit in Powershell..

LG,
Benson
138959
138959 03.06.2019 um 15:45:44 Uhr
Goto Top
Ist $regkey initialisiert? Wenn $regkey keinen Wert hat (NULL) gibts diesen Fehler.
138959
Lösung 138959 03.06.2019 um 15:52:14 Uhr
Goto Top
Also ich bin mal her gegangen und hab eine Workstation in hostname.txt gelegt und bin zeile für zeile durchgegangen:

$computers = gc C:\temp\hostname.txt

#Hier spare ich mir deine Schleife und versuche das ganze mit dem ersten Objekt aus Computers
$computer = $computers;


$key = "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install"
$keytype = [Microsoft.Win32.RegistryHive]::LocalMachine
$RemoteBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype,$computer)

und dann kommt die erste Exception bei mir:
Ausnahme beim Aufrufen von "OpenRemoteBaseKey" mit 2 Argument(en): "Der Netzwerkpfad wurde nicht gefunden.
"
In Zeile:1 Zeichen:1

back-to-top$RemoteBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keyty ...

back-to-top~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ CategoryInfo : NotSpecified: (face-smile , MethodInvocationException
+ FullyQualifiedErrorId : IOException


Danach hat $regkey einen NULL Wert weil $RemoteBase nichts zurückgibt. Musst mal schauen wo es in dieser Zeile hängt.
Die NULL-Reference Exception scheint ein folgefehler zu sein