Skriptausführung via Taskplaner hin und wieder erfolglos
Moin PS-Experten!
Der Windows-Taskplaner führt hier alle paar Stunden ein Skript aus um den Defender upzudaten:
Wer hat eine Erklärung dafür, dass die Kontrollmeldung IMMER kommt, wenn die Versionen nicht übereinstimmen, wohingegen das Update (der Start von mpam-fe.exe) nicht immer ausgeführt wird? Es ist mir ein Rätsel. Da das Skript auf dem selben Share liegt, kann ausgeschlossen werden, dass das Share temporär nicht verfügbar ist.
Mit "nicht immer" meine ich unregelmäßig, völlig regellos. Mal kann ich sehen, dass es 2x in 24 Stunden läuft, wie erwartet, mal läuft es seltsamerweise 3 volle Tage gar nicht (während wie gesagt die Kontrollmeldung IMMER gezeigt wird, wenn die Versionen nicht übereinstimmen).
Der Windows-Taskplaner führt hier alle paar Stunden ein Skript aus um den Defender upzudaten:
$v1 = [version](gci \\server\share\Defenderupdates\mpam-fe.exe).VersionInfo.FileVersion
$v2 = [version](Get-ItemProperty -Path 'HKLM:SOFTWARE\Microsoft\Windows Defender\Signature Updates').AVSignatureVersion
if ($v1 -gt $v2) {\\server\share\Defenderupdates\mpam-fe.exe}
if ($v1 -gt $v2) {msg * Kontrollmeldung!}
Wer hat eine Erklärung dafür, dass die Kontrollmeldung IMMER kommt, wenn die Versionen nicht übereinstimmen, wohingegen das Update (der Start von mpam-fe.exe) nicht immer ausgeführt wird? Es ist mir ein Rätsel. Da das Skript auf dem selben Share liegt, kann ausgeschlossen werden, dass das Share temporär nicht verfügbar ist.
Mit "nicht immer" meine ich unregelmäßig, völlig regellos. Mal kann ich sehen, dass es 2x in 24 Stunden läuft, wie erwartet, mal läuft es seltsamerweise 3 volle Tage gar nicht (während wie gesagt die Kontrollmeldung IMMER gezeigt wird, wenn die Versionen nicht übereinstimmen).
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 673294
Url: https://administrator.de/forum/windows-taskplaner-defender-update-673294.html
Ausgedruckt am: 14.06.2025 um 22:06 Uhr
20 Kommentare
Neuester Kommentar
Moin
was wenn es auf eine Exception läuft?
Hab einfach mal hinter Update ein X gehängt. Also nicht lesbar. Get-Childitem macht es trotzdem.
Bin kein PS Guru. Ggf. Error Handlling anpassen, was bei Fehler Stop erzwingt.
GCI oben läuft durch. Ka wie es sich es sich nun verhält, wenn die Version-Variable $null oder was auch immer ist. Typ [version] kann es ja ggf. nicht sein, wenn Registry unlesbar ist.
Das wäre so mein erster Gedanke.
Get-ItemProperty ist ja relativ simpel. Wenn man es mal 100x Mal nacheinander macht. Ich erinnre mich dunkel dass ich sowas auch mal erzwingen konnte - also den Fehler.
Ist nur geraten und ich weiß auch nicht wie der Vergleich oben mit $null ausgehen würde.
Edit: Konnte es gerade erzwingen, hatte aber die Var vorher nicht entfernt. Da wurde dann weiterausgeführt - trotz Fehler. Wenn die Var nicht initialisiert worden sind dürfte nix ausgeführt werden.
An sinnvollsten wäre es, wenn du es mal mit loggen würdest und die Ergebnisse der Version in die Logdatei schreibst. Ggf. wird es dann klarer was zur der Zeit gelesen wurde.
was wenn es auf eine Exception läuft?
$v2 = [version](Get-ItemProperty -Path 'HKLM:SOFTWARE\Microsoft\Windows Defender\Signature Updatesx').AVSignatureVersion
Get-ChildItem c:\temp
Hab einfach mal hinter Update ein X gehängt. Also nicht lesbar. Get-Childitem macht es trotzdem.
Bin kein PS Guru. Ggf. Error Handlling anpassen, was bei Fehler Stop erzwingt.
# Change the ErrorActionPreference to 'Stop'
$ErrorActionPreference = 'Stop'
# Error message is generated and script stops processing
Write-Error -Message 'Test Error' ; Write-Host 'Hello World'
# Show the ActionPreferenceStopException and the error generated
$Error[0]
$Error[1]
GCI oben läuft durch. Ka wie es sich es sich nun verhält, wenn die Version-Variable $null oder was auch immer ist. Typ [version] kann es ja ggf. nicht sein, wenn Registry unlesbar ist.
Das wäre so mein erster Gedanke.
Get-ItemProperty ist ja relativ simpel. Wenn man es mal 100x Mal nacheinander macht. Ich erinnre mich dunkel dass ich sowas auch mal erzwingen konnte - also den Fehler.
Ist nur geraten und ich weiß auch nicht wie der Vergleich oben mit $null ausgehen würde.
Edit: Konnte es gerade erzwingen, hatte aber die Var vorher nicht entfernt. Da wurde dann weiterausgeführt - trotz Fehler. Wenn die Var nicht initialisiert worden sind dürfte nix ausgeführt werden.
An sinnvollsten wäre es, wenn du es mal mit loggen würdest und die Ergebnisse der Version in die Logdatei schreibst. Ggf. wird es dann klarer was zur der Zeit gelesen wurde.

$v1 = [version](Get-ItemProperty -Path 'HKLM:SOFTWARE\Microsoft\Windows Defender\Signature Updates').AVSignatureVersion
$v2 = [version](Get-ItemProperty -Path 'HKLM:SOFTWARE\Microsoft\Windows Defender\Signature Updatesx').AVSignatureVersion
if ($v1 -gt $v2) {Write-Host 'A'}
Hatte es eben schon wieder gelöscht - dachte Irrweg. Hatte vorher aber Error Handling in der ISE aktiv.
Wenn ich das in ISE kopiere kommt sofort "A".
Gehe immer noch stark davon aus dass z.B. Registry Abfrage fehschlägt.
Error-Handling sollte den Fehler eliminieren.
https://learn.microsoft.com/de-de/powershell/module/microsoft.powershell ...
$ErrorActionPreference = 'Stop'
Liefert Fehler macht aber NICHT weiter. Platziere das mal bitte oben in die erste Zeile. Dann sollte es schon gut sein.
try...catch etc. gibs zwar auch, aber betrifft nur die Zeilen die es umschließt. Denke mit der Preference für dein Script sollte es schon getan sein.
if ($v1 -gt $v2)
Gilt ja für beides. Hab ich mit den Buchstaben "A" simuliert. Ohne Error Handling kann es Amok laufen und macht einfach weiter. Vergleicht die Variablen, obwohl ein Wert Unsinn ist.
$ErrorActionPreference = 'Stop'
Probiere das mal wie gesagt oben aus. Für den Fall das zu einer Zeit mal eben NICHT die Registry z.B. sauber gelesen wird. Dann wird nix weiter ausgeführt und das Log sollte leer sein.
Ob nun "A" kommt oder das was {msg * Kontrollmeldung!} bewirkt ist ja egal. Es rennt aufgrund falscher Meldung weiter durch, da der bool'schle Vergleich true ergibt.
Wenn ich recht habe müsste $ErrorActionPreference alles stoppen, wenn etwas auf einen Hammer läuft.
Gilt ja für beides. Hab ich mit den Buchstaben "A" simuliert. Ohne Error Handling kann es Amok laufen und macht einfach weiter. Vergleicht die Variablen, obwohl ein Wert Unsinn ist.
$ErrorActionPreference = 'Stop'
Probiere das mal wie gesagt oben aus. Für den Fall das zu einer Zeit mal eben NICHT die Registry z.B. sauber gelesen wird. Dann wird nix weiter ausgeführt und das Log sollte leer sein.
Ob nun "A" kommt oder das was {msg * Kontrollmeldung!} bewirkt ist ja egal. Es rennt aufgrund falscher Meldung weiter durch, da der bool'schle Vergleich true ergibt.
Wenn ich recht habe müsste $ErrorActionPreference alles stoppen, wenn etwas auf einen Hammer läuft.
Moin,
Würde das auch eher anfangen.
Spannend ist ja, was $v1 bzw. $v2 zum Zeitpunkt des Fehlers enthalten.
Vielleicht mal für ein paar Tage die beiden Inhalte (mit Zeitstempel) in eine Text-Datei schreiben lassen.
Wenn die zum Zeitpunkt des Fehlers leer sind, sollte auch ein
Würde das auch eher anfangen.
Spannend ist ja, was $v1 bzw. $v2 zum Zeitpunkt des Fehlers enthalten.
Vielleicht mal für ein paar Tage die beiden Inhalte (mit Zeitstempel) in eine Text-Datei schreiben lassen.
Wenn die zum Zeitpunkt des Fehlers leer sind, sollte auch ein
if($v1 > $v2 -and $null -ne $v1 -and $null -ne $v2){…
}
Hallo,
ich glaube du hast hier einen kleinen Denkfehler, dein Regestry Wert ist keine Nummer sondern ein String, von daher wird $1 -gr $2 nie wirklich funktioneren.
Ich vermute du musst $1 und $2 casten, damit ein -gt oder -lt Vergleich funktioniert
grüße

ich glaube du hast hier einen kleinen Denkfehler, dein Regestry Wert ist keine Nummer sondern ein String, von daher wird $1 -gr $2 nie wirklich funktioneren.
Ich vermute du musst $1 und $2 casten, damit ein -gt oder -lt Vergleich funktioniert
[System.Version]"2.7.0.19530" -gt [System.Version]"3.0.0.4080"
grüße

@goodlie
er hast den String doch als Version "konvertiert":
Habe das mal mit dem null getestet:
Ergebnis:
Wenn du also diese Zeile
so abänderst:
Sollte es zu dem Fehlerbild nicht mehr kommen - testen kann ich das hier natürlich nicht hinreichend valide...
er hast den String doch als Version "konvertiert":
$v1 = [version](...)
Habe das mal mit dem null getestet:
$v1 = [version] "1.429.316.0"
$v2 = [version](Get-ItemProperty -Path 'HKLM:SOFTWARE\Microsoft\Windows Defender\Signature Updates2').AVSignatureVersion
Write-Host "V1: $v1"
Write-Host "V2: $v2"
if($v1 -gt $v2){
Write-Host "v1 gt then v2"
} else {
Write-Host "v1 not gt then v2"
}
if($null -ne $v1) {Write-Host "V1: $v1 is not null"}
if($null -ne $v2) {Write-Host "V2: $v1 is not null"}
Ergebnis:
Get-ItemProperty : Cannot find path 'HKLM:\SOFTWARE\Microsoft\Windows Defender\Signature Updates2' because it does not
exist.
At C:\_scripts\Powershell\test.ps1:2 char:17
+ ... = [version](Get-ItemProperty -Path 'HKLM:SOFTWARE\Microsoft\Windows D ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (HKLM:\SOFTWARE\...nature Updates2:String) [Get-ItemProperty], ItemNotFo
undException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand
V1: 1.429.316.0
V2:
v1 gt then v2
1: 1.429.316.0 is not null
Wenn du also diese Zeile
if ($v1 -gt $v2) {\\server\share\Defenderupdates\mpam-fe.exe}if ($v1 -gt $v2) {\\server\share\Defenderupdates\mpam-fe.exe
if (($v1 -gt $v2) -and ($null -ne $v1) -and ($null -ne $v2)) {\\server\share\Defenderupdates\mpam-fe.exe}if ($v1 -gt $v2) {\\server\share\Defenderupdates\mpam-fe.exe
Zitat von @godlie:
ich glaube du hast hier einen kleinen Denkfehler, dein Regestry Wert ist keine Nummer sondern ein String, von daher wird $1 -gr $2 nie wirklich funktioneren.
ich glaube du hast hier einen kleinen Denkfehler, dein Regestry Wert ist keine Nummer sondern ein String, von daher wird $1 -gr $2 nie wirklich funktioneren.
Hier wird ein VERSION Objekt erstellt. Wo die KeysMajor Minor Build Revision gefüllt werden.
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
Wenn wir das Objekt zerlegen und uns mal "Major" asnchauen so verbergen sich dahinter dann Integer Werte.
Damit ist es vergleichbar. [version] presst die Infos aus dem Filesystem und der Registry in dieses Format mit bis zu 4 Zahlen Werten.
Ich kann es reproduzieren, wen nich die Registry Abfrage manipuliere! Dann wäre $v2 kaputt - NULL. Damit wird dann der Vergleich immer wahr und er schreibt auch das Log immer.
@DerWoWusste ggf. wird auch Registry zeitweise nicht als Laufwerk dargestellt, wenn du das Script ausführst.
(Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Signature Updates").AVSignatureVersion

HKLM ist ja ein "virt." Laufwerk. Schreib von daher mal den Pfad wie oben mit Registry::HKEY_LOCAL_MACHINE... aus.
Wenn du in der PowerShell
cd "HKLM:/"
eingibst, so wechselt es von C:\ auf HKLM:\ Beachte den Prompt.
@DerWoWusste ggf. ist also die registry zur Laufzeit im Taskplaner ann TEILWEISE nicht sauber gemapped.
Der vollständige Pfade KÖNNTE hier helfen.
Ansonten kann man noch - wie @em-pie schon aufzeigte - Fehlerbehandlung weiter einbauen. Wenn es hier um das Filesytem geht, in das die Registry quasi gemapped ist:
Test-Path -Path "HKLM:/"
Das könnte ich mir gut vorstellen. Dass zur Laufzeit irgendwann, spontan, weil in China ein Sack Reis umgekippt ist, genu das Laufwerk HLKM eben mal NICHT da ist.
Entweder du machst globale Fehlerbehandlung oder du baust was ein. So wie @em-pie es schrieb oder einen lustigen Test-Path.
Test-Path -Path "HKLM:/"
Würde also ggf. auch verhindern dass der Wert NULL wird und das Script weiter läfut.
Registry::HKEY_LOCAL_MACHINE\SOFTWARE\ .....
Könnte dafür sorgen dass eben nicht über HKLM gegangen wird und die Werte trotzdem kommen.
Ich vermute sehr stark das zufällig und spontan "HLKM:/" nicht einghängt ist und es darum versagt.
Zitat von @DerWoWusste:
Irgendwas sagt mir, dass Ihr das Problem nicht versteht. Vielleicht bin ich es auch.
Wenn ich das Skript interaktiv ausführe, so geht es immer.
Nur über den Taskplaner kommt es manchmal zu diesen unerklärlichen Aussetzern.
Irgendwas sagt mir, dass Ihr das Problem nicht versteht. Vielleicht bin ich es auch.
Wenn ich das Skript interaktiv ausführe, so geht es immer.
Nur über den Taskplaner kommt es manchmal zu diesen unerklärlichen Aussetzern.
Ja nee, ich hab noch mal nachgedacht!
NULL Fehler von oben würde heisse das IMMER die EXE ausgeführt wird. Dachte du meinst sowas. Dann wäre also in deinen Fall immer eine Installation angestoßen worden - auch wenn die Version nicht größer ist.
Was ist mit Get-ChildItem und der EXE. Überlege gerade ob die duch das Kommando noch blockiert ist und nicht ausgeführt wird.
Du könntest ein Start-Sleep davor setzen.
Zitat von @godlie:
@em-pie
@Crusher79
Danke für den Hinweis, ich hatte das [version] übersehen im ersten Post
@em-pie
@Crusher79
Danke für den Hinweis, ich hatte das [version] übersehen im ersten Post
Alles gut. Ich hab übersehen dass es scheinbar genau umgekehrt ist ^^
Mit meinen tollen Fehler sollte die EXE ja immer ausgeführt werden - Tut sie aber nicht. Soll sie aber ja scheinbar. Mist.
Zitat von @DerWoWusste:
Update: es hat mit Versionsabfragen mal gar nichts zu tun.
Selbst wenn das Skript nur aus einer Zeile besteht:
\\server\share\defenderupdates\mpam-fe.exe
Schlägt es auf Rechnern hin und wieder fehl im Taskplaner, während es interaktiv (mit dem selben Benutzer, der im Task steht, nämlich "system" ausgeführt) IMMER läuft.
Update: es hat mit Versionsabfragen mal gar nichts zu tun.
Selbst wenn das Skript nur aus einer Zeile besteht:
\\server\share\defenderupdates\mpam-fe.exe
Schlägt es auf Rechnern hin und wieder fehl im Taskplaner, während es interaktiv (mit dem selben Benutzer, der im Task steht, nämlich "system" ausgeführt) IMMER läuft.
Dann dürfte ja $LastExitCode nicht 0 sein - fehlerfrei.
Du könnest Start-Sleep nehemn, wenn der Code nicht 0 ist und es ein paar Sekunden später nochmal ausführen.
Wenn die Binary im Netz liegt ggf. kurzer Wischer und Übertragungsfehler. Holzhammer wäre es nochmal zu wiederholen.
try ... catch ... finally könnte man ggf. auch noch hernehmen. Kniffelig.
Zitat von @DerWoWusste:
Update: es hat mit Versionsabfragen mal gar nichts zu tun.
Selbst wenn das Skript nur aus einer Zeile besteht:
\\server\share\defenderupdates\mpam-fe.exe
Schlägt es auf Rechnern hin und wieder fehl im Taskplaner, während es interaktiv (mit dem selben Benutzer, der im Task steht, nämlich "system" ausgeführt) IMMER läuft.
Update: es hat mit Versionsabfragen mal gar nichts zu tun.
Selbst wenn das Skript nur aus einer Zeile besteht:
\\server\share\defenderupdates\mpam-fe.exe
Schlägt es auf Rechnern hin und wieder fehl im Taskplaner, während es interaktiv (mit dem selben Benutzer, der im Task steht, nämlich "system" ausgeführt) IMMER läuft.
Vielleicht kommt die PS (partiell) nicht an den UNC-Pfad dran - oder wird geblockt!?
Hilft es, wenn du ein
Start-Process()
nutzt, um die mpam-fe.exe zu starten (auch wenn du gerade auf batch schwenkst)?Und was passiert, wenn du in der Powershell noch ein Push-Location() davor setzt:
...
Push-Location -Path ...
Start-Process -FilePath ...
Ich würde im PS1 den Programmpfad in "" setzen, weil da ein "-" im Namen ist, was sonst auch als Operator zum Einsatz kommt. Zwar würde das nicht erklären, warum es mal geht und mal nicht, aber es wäre ein Ansatz.
Weiterhin würde ich wissen wollen, ob es ggf. daran liegt, dass die EXE zeitweise - warum auch immer - nicht verfügbar ist. Das könnte man mit einem "If(Test-Path "...") {"schreibe ins Log"} abfackeln.
Ebenso könnte man die EXE mittels "Start-Process" starten, was u.U. "bessere" Fehlermeldungen bringt.
Weiterhin würde ich wissen wollen, ob es ggf. daran liegt, dass die EXE zeitweise - warum auch immer - nicht verfügbar ist. Das könnte man mit einem "If(Test-Path "...") {"schreibe ins Log"} abfackeln.
Ebenso könnte man die EXE mittels "Start-Process" starten, was u.U. "bessere" Fehlermeldungen bringt.