PowerShell über Aufgabenplanung Löschung Dateien älter als X Tage auf Netzwerkfreigaben
Hallo Community,
ich verzweifle gerade an einer Aufgabenstellung und benötige euer Schwarmwissen und Ideen. Ich habe eine PowerShell-Skript geschrieben, das vielleicht nicht schön ist aber dennoch funktioniert, wenn ich es in der PowerShell ISE (Admin) oder auch in PowerShell als anderer Benutzer ausführe.
Kurz zum Hintergrund der Aufgabenstellung:
1. Es sollen alle Dateien aus zwei Ordnern gelöscht werden, die älter als 30 Tage sind. (Server1)
- auf diese Freigabe haben aber nur Administratoren und bestimmt Service-Accounts zugriff.
2. Zusätzlich sollten alle Dateien aus einem TEMP-Verzeichnis gelöscht werden die älter als 1 Tag sind. (Server2)
- auf diese Freigabe haben aber nur Administratoren und bestimmt Service-Accounts zugriff.
3. Weiter wird ein Protokoll in eine Textdatei geschrieben, in dem steht wann das Skript ausgeführt wurde, welche Dateien gelöscht wurden und ob es einen Fehler gab. Zusätzlich wird das Logs täglich neu geschrieben und für 60 Tage vorgehalten.
Nun aber nach dem ganzen Hintergrund zu meinem Problem. Ich möchte das Skript nicht selbst ausführen sondern einen Task in der Aufgabenplanung anlegen, der das Skript beispielsweise alle 24 Stunden gegen 7 Uhr ausführt.
Der Task war auch schnell angelegt, ist schließlich nicht das erste Mal, aber es passiert leider überhaupt nichts. Der Task wurde für eine Service-Account erstellt wie folgend.
Wenn ich den Task auf meinem Windows Server 2022 mit meinem Admin-Account mit "Run only when user is logged on" ausführe, funktioniert alles wie am Anfang beschrieben.
Hat jemand eine Idee, was ich falsch gemacht habe oder wo mein Denkfehler ist? Muss ich die Benutzerinformationen für den Service-Account auch nochmal im Skript eintragen oder reicht es aus, wenn ich den Task mit diesem Service-Account ausführen lasse? Sollten die Benutzerinformationen ins das Skript müssen, frage ich mich wie ich das am besten machen.
Vielen Dank bereits im Voraus!
Grüße
Mischl
ich verzweifle gerade an einer Aufgabenstellung und benötige euer Schwarmwissen und Ideen. Ich habe eine PowerShell-Skript geschrieben, das vielleicht nicht schön ist aber dennoch funktioniert, wenn ich es in der PowerShell ISE (Admin) oder auch in PowerShell als anderer Benutzer ausführe.
Kurz zum Hintergrund der Aufgabenstellung:
1. Es sollen alle Dateien aus zwei Ordnern gelöscht werden, die älter als 30 Tage sind. (Server1)
- auf diese Freigabe haben aber nur Administratoren und bestimmt Service-Accounts zugriff.
2. Zusätzlich sollten alle Dateien aus einem TEMP-Verzeichnis gelöscht werden die älter als 1 Tag sind. (Server2)
- auf diese Freigabe haben aber nur Administratoren und bestimmt Service-Accounts zugriff.
3. Weiter wird ein Protokoll in eine Textdatei geschrieben, in dem steht wann das Skript ausgeführt wurde, welche Dateien gelöscht wurden und ob es einen Fehler gab. Zusätzlich wird das Logs täglich neu geschrieben und für 60 Tage vorgehalten.
# Variablen definieren
$netzwerkpfad1 = "\\Server1\Freigabe1\Eingang\1\"
$netzwerkpfad2 = "\\Server1\Freigabe1\Ausgang\1\"
$temppfad = "\\Server2\Temp"
$logDateiname = "Log_Script"
$logVerzeichnis = "\\Server2\Log"
$maxAnzahlLogs = 60
# Schritt 1: Dateien im Netzwerkpfaden älter als 30 Tage löschen
$gelöschteNetzwerkdateien1 = Get-ChildItem -Path $netzwerkpfad1 | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) }
$gelöschteNetzwerkdateien1 | Remove-Item -Force
Start-Sleep -Seconds 5 # Pause für 5 Sekunden
$gelöschteNetzwerkdateien2 = Get-ChildItem -Path $netzwerkpfad2 | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) }
$gelöschteNetzwerkdateien2 | Remove-Item -Force
Start-Sleep -Seconds 5 # Pause für 5 Sekunden
# Schritt 2: Dateien im Temp Pfad älter als 1 Tage löschen
$gelöschteTempdateien = Get-ChildItem -Path $temppfad | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-1) }
$gelöschteTempdateien | Remove-Item -Force
Start-Sleep -Seconds 5 # Pause für 5 Sekunden
# Schritt 3: Aktuelle fortlaufende Nummer basierend auf dem Tag erhalten
$fortlaufendeNummer = Get-Date -Format "MMdd"
# Schritt 4: Speichern von Ausführungsstatus in Logdatei
$dateiname = "${logDateiname}_$fortlaufendeNummer.txt"
$dateipfad = Join-Path -Path $logVerzeichnis -ChildPath $dateiname
# Schritt 5: Prüfen und löschen der ältesten Datei, wenn mehr als die maximale Anzahl vorhanden ist
$dateien = Get-ChildItem -Path $logVerzeichnis -Filter "${logDateiname}_*.txt" | Sort-Object CreationTime
if ($dateien.Count -ge $maxAnzahlLogs) {
$zuLöschendeDateien = $dateien[0..($dateien.Count - $maxAnzahlLogs)]
$zuLöschendeDateien | ForEach-Object {
Remove-Item -Path $_.FullName -Force
}
}
# Schritt 6: Schreibe Datum, Zeit und Ausführungsstatus in Logdatei
Add-Content -Path $dateipfad -Value (Get-Date -Format "dd.MM.yyyy HH:mm:ss") -NoNewline
Add-Content -Path $dateipfad -Value "`t`t$logDateiname`tSkript zum Löschen wird ausgeführt..."
# Schritt 7: Schreibe gelöschte Dateinamen in Logdatei
if ($gelöschteNetzwerkdateien1.Count -gt 0) {
Add-Content -Path $dateipfad -Value "`t`t`t`t`t`t`t`tGelöschte Netzwerkdateien Schritt 1:"
$gelöschteNetzwerkdateien1 | ForEach-Object {
Start-Sleep -Seconds 5 # Pause für 5 Sekunden
Add-Content -Path $dateipfad -Value "`t`t`t`t`t`t`t`t`t$($_.FullName)"
}
}
if ($gelöschteNetzwerkdateien2.Count -gt 0) {
Add-Content -Path $dateipfad -Value "`t`t`t`t`t`t`t`tGelöschte Netzwerkdateien Schritt 2:"
$gelöschteNetzwerkdateien2 | ForEach-Object {
Start-Sleep -Seconds 5 # Pause für 5 Sekunden
Add-Content -Path $dateipfad -Value "`t`t`t`t`t`t`t`t`t$($_.FullName)"
}
}
if ($gelöschteTempdateien.Count -gt 0) {
Add-Content -Path $dateipfad -Value "`t`t`t`t`t`t`t`tGelöschte Temp Dateien:"
$gelöschteTempdateien | ForEach-Object {
Start-Sleep -Seconds 5 # Pause für 5 Sekunden
Add-Content -Path $dateipfad -Value "`t`t`t`t`t`t`t`t`t$($_.FullName)"
}
}
# Schritt 8: Schreibe Datum, Zeit und Ausführungsstatus in Logdatei
$ausführungsstatus = if ($?) { "erfolgreich" } else { "mit Fehler" }
Add-Content -Path $dateipfad -Value (Get-Date -Format "dd.MM.yyyy HH:mm:ss") -NoNewline
Add-Content -Path $dateipfad -Value "`t`t$logDateiname`tSkript wurde $ausführungsstatus ausgeführt." -Force
Nun aber nach dem ganzen Hintergrund zu meinem Problem. Ich möchte das Skript nicht selbst ausführen sondern einen Task in der Aufgabenplanung anlegen, der das Skript beispielsweise alle 24 Stunden gegen 7 Uhr ausführt.
Der Task war auch schnell angelegt, ist schließlich nicht das erste Mal, aber es passiert leider überhaupt nichts. Der Task wurde für eine Service-Account erstellt wie folgend.
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2023-09-19T11:08:17.1892535</Date>
<Author>DOMÄNE\ADMIN1</Author>
<URI>\Beispiele\deleteFiles</URI>
</RegistrationInfo>
<Triggers>
<CalendarTrigger>
<StartBoundary>2023-09-19T07:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByDay>
<DaysInterval>1</DaysInterval>
</ScheduleByDay>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>A-2-2-22-22222222-2222222222-2222222222-2222222</UserId>
<LogonType>Password</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>P1D</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
<Arguments>-ExecutionPolicy Bypass -File "E:\deleteFiles-5.ps1"</Arguments>
</Exec>
</Actions>
</Task>
Wenn ich den Task auf meinem Windows Server 2022 mit meinem Admin-Account mit "Run only when user is logged on" ausführe, funktioniert alles wie am Anfang beschrieben.
Hat jemand eine Idee, was ich falsch gemacht habe oder wo mein Denkfehler ist? Muss ich die Benutzerinformationen für den Service-Account auch nochmal im Skript eintragen oder reicht es aus, wenn ich den Task mit diesem Service-Account ausführen lasse? Sollten die Benutzerinformationen ins das Skript müssen, frage ich mich wie ich das am besten machen.
Vielen Dank bereits im Voraus!
Grüße
Mischl
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 1515451775
Url: https://administrator.de/forum/powershell-ueber-aufgabenplanung-loeschung-dateien-aelter-als-x-tage-auf-netzwerkfreigaben-1515451775.html
Ausgedruckt am: 15.03.2025 um 08:03 Uhr
5 Kommentare
Neuester Kommentar
Hi,
Wenn du die Suchfunktion genutzt hättest, hättest du eventuell das gefunden:
Aufgabenplanung Backup
Da habe ich ziemlich genau beschrieben wie man einen Scheduled Task anlegt.
Ach! Ganz wichtig! Keine Umlaute im Skript!
Grüße
Wenn du die Suchfunktion genutzt hättest, hättest du eventuell das gefunden:
Aufgabenplanung Backup
Da habe ich ziemlich genau beschrieben wie man einen Scheduled Task anlegt.
Ach! Ganz wichtig! Keine Umlaute im Skript!
Grüße

Moin,
ohne einen konkreten Tipp würde ich z.B. in die erste Zeile ein Start-Transcript mit passendem LiteralPath einbauen (Stop-Transcript am Ende des Scripts). Dann kannst Du schon mal - unabhängig von den erzeugten EventLogs zum SchTask - sehen, ob Deine Kommandozeile korrekt gestartet wird (scheint sie ja zu tun, da der SchTask unter bestimmten Umständen anläuft).
Im selben Atemzug könntest Du noch mal gucken, ob Du die Delays von 5s tats. brauchst - ist mir seit Jahren nicht mehr untergekommen, so‘n „warten auf‘s Dateisystem“…
Und noch 'n Kommentar zur ISE: der Konsolen-Host ist ein Anderer, als der Host der powershell.exe oder pwsh.exe und verhält sich (zugegeben nur in „edge cases“) anders. Ich hatte bei den alten WMI-CmdLets und bei ShouldProcess und -Debug abweichendes Verhalten bei dem, was in die Pipeline geht, festgestellt (oder hab‘ mies diagnostiziert 😉)
Mit dem Start-Transcript und ordentlich Write-Host oder Wite-Debug kommst Du der Ursache auf Jeden schnell auf die Spur.
Viel Erfolg!
ohne einen konkreten Tipp würde ich z.B. in die erste Zeile ein Start-Transcript mit passendem LiteralPath einbauen (Stop-Transcript am Ende des Scripts). Dann kannst Du schon mal - unabhängig von den erzeugten EventLogs zum SchTask - sehen, ob Deine Kommandozeile korrekt gestartet wird (scheint sie ja zu tun, da der SchTask unter bestimmten Umständen anläuft).
Im selben Atemzug könntest Du noch mal gucken, ob Du die Delays von 5s tats. brauchst - ist mir seit Jahren nicht mehr untergekommen, so‘n „warten auf‘s Dateisystem“…
Und noch 'n Kommentar zur ISE: der Konsolen-Host ist ein Anderer, als der Host der powershell.exe oder pwsh.exe und verhält sich (zugegeben nur in „edge cases“) anders. Ich hatte bei den alten WMI-CmdLets und bei ShouldProcess und -Debug abweichendes Verhalten bei dem, was in die Pipeline geht, festgestellt (oder hab‘ mies diagnostiziert 😉)
Mit dem Start-Transcript und ordentlich Write-Host oder Wite-Debug kommst Du der Ursache auf Jeden schnell auf die Spur.
Viel Erfolg!
Ich denke ich habe den Fehler gefunden:
In deinem Task rufst du die Powershell so auf:
Das andere Problem wird sein, dass du als Pfad zum Scrpt ein E:\ angibst. Könnte sein, dass das auf deinem Server nicht mehr stimmt. Verwende besser den FQDN zum Script,
In deinem Task rufst du die Powershell so auf:
<Exec>
<Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
<Arguments>-ExecutionPolicy Bypass -File "E:\deleteFiles-5.ps1"</Arguments>
</Exec>
- Auf Server ist es aber nicht ungewöhlich, dass %SystemDrive% etwas anderes als C:\ ist.
- besser die die Comspec callen und den Rest als Argument mitgeben mit %SYSTEMROOT%:
<Exec>
<Command>cmd.exe</Command>
<Arguments>/c %SYSTEMROOT%\System32\WindowsPowershell\v1.0\powershell.exe -ExecutionPolicy Bypass -File "E:\deleteFiles-5.ps1"</Arguments>
</Exec>
Das andere Problem wird sein, dass du als Pfad zum Scrpt ein E:\ angibst. Könnte sein, dass das auf deinem Server nicht mehr stimmt. Verwende besser den FQDN zum Script,