ScheduledJobs

Gleich an Tag 2 begegnen wir einem sehr speziellen Command Set-ScheduledJobOptions. Führt man es in PowerShell aus erscheint erstmal eine Fehlermeldung:

Set-ScheduledJobOption
Set-ScheduledJobOption: The 'Set-ScheduledJobOption' command was found in the module 'PSScheduledJob', but the module could not be loaded. For more information, run 'Import-Module PSScheduledJob'.

Ok, also das Modul importieren

Import-Module PSScheduledJob
Import-Module: Module 'PSScheduledJob' is blocked from loading using Windows PowerShell compatibility feature by a 'WindowsPowerShellCompatibilityModuleDenyList' setting in PowerShell configuration file.

Das Modul kann nicht geladen werden weil es auf der ModuleDenyList ist. Das betrifft Module die nicht PowerShell kompatibel sind und z.B. nur von der Windows Powershell benutzt werden können. Das bedeutet das Command ist nicht Crossplatform und nur unter Windows in der “alten” Windows Powershell verfügbar.

Windows Powershell basiert auf .Net Framework 4.5 wobei PowerShell ab Version 6.0 auf .Net Core 2.0 basiert (dem platformunabhängigen .Net) .Net Core und somit auch PowerShell laufen damit auf Windows, Linux und Mac.

Zurück zu unserem Command und zur Windows PowerShell, startet man dieses kann man Set-ScheduledJobOption aufrufen und es wird nach dem ersten Input Paramter gefragt. Die abfrage mit STRG+C einfach abbrechen.

Set-ScheduledJobOption macht nur sinn mit einem ScheduledJob. Also schauen wir mal was es so gibt mit dem Get-Equivalent

Get-ScheduledJob

Die Ausgabe beleibt leer, es gibt also gerade keine Scheduled Jobs auf dem Windows System.

Register-ScheduledJob

Einen ScheduledJob ist ein Hintergrund Task der einmalig oder mehrmals, nach einem Zeitplan abläuft. Diese können über die PowerShell oder dem Task Scheduler (zu Deutsch “Aufgabenplaner”) angezeigt und bearbeitet werden. Mit Register-ScheduledJob kann ein neuer Registiert werden. Hier generieren wird ein Trigger generiert und dann der Job Registriert. Dabei handelst es sich um einen ScriptBlock der jedes mal ausgeführt, in dem fall wird ein Bild von einer Webcam abeholt und lokal gespiechert.

$t = New-JobTrigger -Daily -At "09:03 AM"
$o = New-ScheduledJobOption -StartIfOnBattery
Register-ScheduledJob -Name "Download WebCam Image" -ScheduledJobOption $o -Trigger $t -ScriptBlock {
    $day = Get-Date -Format dd
    $month = Get-Date -Format MM
    $year = Get-Date -Format yyyy
    $now = Get-Date
    $timeRoundDown = $now.AddMinutes(-$now.Minute % 30)
    $time = $timeRoundDown.ToString('HHmm')
    $url = "https://www.addicted-sports.com/fileadmin/webcam/starnbergersee/$year/$month/$day/${time}_lt.jpg"
    curl $url -o c:/webcam/${year}_${month}_${day}_${time}.jpg
}

gibt folgendes zurück

Id         Name            JobTriggers     Command                                  Enabled
--         ----            -----------     -------                                  -------
1          Download Web... 0               ...                                      True

Solange der ScheduledJob noch keinen Trigger hat wird er auch nicht ausgelöst (kann aber registriert werden) deswegen geben wir mit $t ein job trigger an, täglich um 10:05 Uhr morgens. Die 5 Minuten Verzögerung sollen sicherstellen das, dass 10 Uhr Foto auch wirklich zu finden ist, die Webcam macht nur alle 30 Minuten Bilder und dieses muss auch unter der URL zu finden sein. Deswegen rundet $timeRoundDown abwärts, zur letzen halben Stunde.

Get-ScheduledJob zeigt den Job jetzt auch an mit der selben Ausgabe wie zuvor.

Der Trigger kann auch abgeändert werden und jede Stunde ein Bild zu holen:

$t = New-JobTrigger -once -At "10:05 AM" -RepetitionInterval (New-TimeSpan -Hours 1) -RepetitionDuration ([TimeSpan]::MaxValue)

Hierbei definiert -Once -At "10:05" den einmaligen startpunkt, das nächste 10:05 Uhr. Entweder am selben Tag (wenn vor 10:05 Uhr ausgeführt) oder am kommenden (wenn nach 10:05 Uhr ausgeführt). Danach wird es jede Stunde wiederholt -RepetitionInterval (New-TimeSpan -Hours 1) bis zur unendlichkeit -RepetitionDuration ([TimeSpan]::MaxValue) welches mit [TimeSpan]::MaxValue angegeben wird. Alternativ könnte man hier auch -RepetitionDuration (New-TimeSpan -Day 7) angegeben dann würde der Job nur eine Woche lang ausgeführt.

Get-ScheduledJobOptions & Set-ScheduledJobOptions

Endlich kommt der Befehl zum Einsatz der gestern ausgewält wurde Set-ScheduledJobOptions. Wo es Set- gibt, gibt es meist auch ein Get. Mit Get-ScheduledJobOptions schauen wir uns die Settings an die automatisch angelegt wurden:

Get-ScheduledJobOption -Name "Download WebCam Image"
StartIfOnBatteries     : False
StopIfGoingOnBatteries : True
WakeToRun              : False
StartIfNotIdle         : True
StopIfGoingOffIdle     : False
RestartOnIdleResume    : False
IdleDuration           : 00:10:00
IdleTimeout            : 01:00:00
ShowInTaskScheduler    : True
RunElevated            : False
RunWithoutNetwork      : True
DoNotAllowDemandStart  : False
MultipleInstancePolicy : IgnoreNew
JobDefinition          : Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition

Wie man vermuten könnte lassen sich all diese Settings mit Set-ScheduledJobOption wiederum setzen. Die intressantesten dürften die folgenden sein:

StartIfOnBatteries: Ist das setting auf True wird der Job auch ausgeführt wenn der PC oder eher Laptop nur auf Batterie läuft. Bei False wird der Task übersprungen. Der Paramter dafür ist -StartIfOnBattery

WakeToRun: Ist der Wert gesetzt wird der PC aus dem Standby/Hybernation. Das kann für bestimmte aufgaben sehr wichtig sein, die umbedingt abgearbeitet werden müssen. Der Paramter dafür ist -WakeToRun

RunWithoutNetwork: Ist das Setting auf True gesetzt wird Task nur ausgeführt wenn eine Netzwerkverbindung vorhanden ist. Das wäre für den WebCam Job recht nütlich. Der Paramter dafür ist -RequireNetwork

RunElevated: Ist der Paramter angegeben wird der Job als Admin, mit allen Rechten, ausgeführt. Der Paramter dafür ist -RunElevated

Die Einstellungen können jetzt nach unseren Vorstellungen geändert werden:

Get-ScheduledJobOption -Name "Download WebCam Image" | Set-ScheduledJobOption -RequireNetwork -StartIfOnBattery

Fehler & Logs

Die logs befinden sich unter %homepath%\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs. Für jeden Scheduled Job gibt es dort einen Ordner mit dem entsprechenden Namen. Darin befindet sich das ScheduledJobDefinition.xml welches den ScheduledJob beschreibt. Ausserdem gibt es einen Output-Ordner indem sich für jede ausführung ein Results.xml udn ein Status.xml befindet. Die Results.xml enthält evtl. Fehlermeldungen und kann zum Fehlersuchen benutzt werden.

tree /f
Folder PATH listing
Volume serial number is 16AB-7E05
C:.
└───Download WebCam Image
    │   ScheduledJobDefinition.xml
    │
    └───Output
        └───20230824-090301-263
                Results.xml
                Status.xml

Register-ScheduledJobOptions Set-ScheduledJobOptions

Nächstes Commando:

Get-Command | Get-Random

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Set-DtcLog                                         1.0.0.0    MsDtc

Eher unintressant - Set-DtcLog setzt die Distributed Transaction Coordinator (DTC) Log Settings. Laut Wikipedia:

Der Distributed Transaction Coordinator, kurz DTC, ist ein Systemdienst auf Microsoft-Windows-NT-basierten Betriebssystemen, der zur Koordination atomarer Operationen beim Einsatz verteilter Anwendungsszenarien verwendet wird.

Bisher war mein intresse die Log Settings dieses Dienstes zu ändern äusserst gering 😊

Auf zum nächsten

Get-Command | Get-Random

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Remove-SmbServerCertificateMapping                 2.0.0.0    SmbShare

Auch eher ein sehr spezielles Kommando, wird z.B. bei SMB over QUICK benutzt. Also nochmal:

 Get-Command | Get-Random

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Cmdlet          Write-Verbose                                      7.0.0.0    Microsoft.PowerShell.Utility

Schon besser, ein äussert nütliches Kommando in Scripten.