Script funktionier im ISE, aber nicht wenn ich es per cmd aufrufe
Hallo
Ich habe hier ein Script das im Powershell ISE einwandfrei funktioniert.
Es kopiert sobald neue Dateien in einem Verzeichnis geschrieben werden, diese noch auf einem anderen Server.
Wenn ich es in einer Batch starte, dann kopiert er mir die Dateien nicht mehr.
Ich rufe es normalerweise so auf:
Jetzt wo es nicht funktionert, natürlich ohne -WindowStyle Hidden und /min
Das Script selbst ist dieses hier:
Wenn ich diesen Code im ISE Starte und neue Dateien kommen, kopiert er mir diese auch auf den Zielpfad.
Allerdings wenn ich das Script dann per Batch starte, zeigt er mir nur noch an, daß die Datei erstellt wird, aber nicht mehr das sie kopiert wird.
Weiß hier zufällig einer weshalb das so ist, bzw. wie man das gelöst bekommt?
Ich habe hier ein Script das im Powershell ISE einwandfrei funktioniert.
Es kopiert sobald neue Dateien in einem Verzeichnis geschrieben werden, diese noch auf einem anderen Server.
Wenn ich es in einer Batch starte, dann kopiert er mir die Dateien nicht mehr.
Ich rufe es normalerweise so auf:
start /min powershell -WindowStyle Hidden -Command "& {$host.ui.RawUI.WindowTitle = 'Copy-Server'; C:\Batch\script\Copy.ps1 }"
Jetzt wo es nicht funktionert, natürlich ohne -WindowStyle Hidden und /min
Das Script selbst ist dieses hier:
$verzeichnisse = @{
"\\server19\Vision\EM\ST300\xxxx\OK" = "\\server11\INCOME\EM\ST300"
"\\server19\Vision\EM\ST500\xxxx\OK" = "\\server11\INCOME\EM\ST500"
"\\server19\Vision\EM\ST600\xxxx\OK" = "\\server11\INCOME\EM\ST600"
"\\server19\Vision\EM\ST700\xxxx\OK" = "\\server11\INCOME\EM\ST700"
}
# Überwachungsfilter
$filter = "*.*"
$watchers = @()
# Erstelle einen FileSystemWatcher für jeden Quellpfad
foreach ($quelle in $verzeichnisse.Keys) {
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $quelle
$watcher.Filter = $filter
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$eventIdentifier = "FileCreated_$($quelle.Replace('\', '_').Replace(':', ''))"
# Event, das ausgelöst wird, wenn eine neue Datei erstellt wird
$event = Register-ObjectEvent -InputObject $watcher -EventName Created -SourceIdentifier $eventIdentifier -Action {
$neueDatei = $Event.SourceEventArgs.FullPath
Write-Host "Neue Datei erstellt: $neueDatei"
# Finde das passende Zielverzeichnis
$zielVerzeichnis = $verzeichnisse.GetEnumerator() | Where-Object { $neueDatei.StartsWith($_.Key) } | ForEach-Object { $_.Value }
if ($zielVerzeichnis -eq $null) {
#Write-Host "Zielverzeichnis nicht gefunden für: $neueDatei"
return
}
# Bestimme den relativen Pfad der Datei
$relativerPfad = (Get-Item $neueDatei).FullName.Substring($quelle.Length + 1)
# Erstelle die Unterverzeichnisse im Zielverzeichnis, falls sie nicht existieren
$zielPfad = Join-Path $zielVerzeichnis $relativerPfad
$zielVerzeichnis = Split-Path $zielPfad
if (-not (Test-Path $zielVerzeichnis)) {
New-Item -Path $zielVerzeichnis -ItemType Directory -Force
Write-Host "Unterverzeichnis erstellt: $zielVerzeichnis"
}
#Kopiere die neue Datei zum Zielverzeichnis
Copy-Item -Path $neueDatei -Destination $zielPfad -Force
Write-Host "Datei wurde nach $zielPfad kopiert."
}
$watchers += $watcher
Write-Host "Überwachung für $quelle gestartet."
}
try {
while ($true) {
# Unendliche Schleife zum Aufrechterhalten des Skripts
Start-Sleep -Seconds 1
}
} finally {
foreach ($watcher in $watchers) {
$eventIdentifier = "FileCreated_$($watcher.Path.Replace('\', '_').Replace(':', ''))"
Unregister-Event -SourceIdentifier $eventIdentifier
$watcher.Dispose()
}
}
Wenn ich diesen Code im ISE Starte und neue Dateien kommen, kopiert er mir diese auch auf den Zielpfad.
Allerdings wenn ich das Script dann per Batch starte, zeigt er mir nur noch an, daß die Datei erstellt wird, aber nicht mehr das sie kopiert wird.
Weiß hier zufällig einer weshalb das so ist, bzw. wie man das gelöst bekommt?
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 72439107725
Url: https://administrator.de/forum/script-funktionier-im-ise-aber-nicht-wenn-ich-es-per-cmd-aufrufe-72439107725.html
Ausgedruckt am: 23.12.2024 um 05:12 Uhr
6 Kommentare
Neuester Kommentar
Stichwort Variable Scope
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell ...
Dein Code im Action-Eventblock wird in einem anderen Scope ausgeführt und kennt deswegen deine Variable $verzeichnisse nicht, ergo kein Zielpfad ergo keine Kopie da du mit return das Event in Zeile 32 vorzeitig verlässt.
Also übergebe die Variable entweder per -MessageData Parameter an den Action-Scriptblock oder definiere die Variable als "Globale" Variable. Globale Variablen sind aber in der Regel schlechter Stil daher hier mal ein
Beispiel mit übergabe via MessageData
Das erledigt dann auch gleich das super ineffektive Ermitteln des Zielpfades in deinem Code gleich mit.
☠️
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell ...
Dein Code im Action-Eventblock wird in einem anderen Scope ausgeführt und kennt deswegen deine Variable $verzeichnisse nicht, ergo kein Zielpfad ergo keine Kopie da du mit return das Event in Zeile 32 vorzeitig verlässt.
Also übergebe die Variable entweder per -MessageData Parameter an den Action-Scriptblock oder definiere die Variable als "Globale" Variable. Globale Variablen sind aber in der Regel schlechter Stil daher hier mal ein
Beispiel mit übergabe via MessageData
Das erledigt dann auch gleich das super ineffektive Ermitteln des Zielpfades in deinem Code gleich mit.
☠️
Moin,
Bin mir unsicher, ob ich falsch liege... aber das Script geht nie aus der While-Schleife raus.
Also wird es letztlich auch nie die Watcher disposen, oder?
Korrigiert mich gerne
VG
try {
while ($true) {
# Unendliche Schleife zum Aufrechterhalten des Skripts
Start-Sleep -Seconds 1
}
} finally {
foreach ($watcher in $watchers) {
$eventIdentifier = "FileCreated_$($watcher.Path.Replace('\', '_').Replace(':', ''))"
Unregister-Event -SourceIdentifier $eventIdentifier
$watcher.Dispose()
}
}
Bin mir unsicher, ob ich falsch liege... aber das Script geht nie aus der While-Schleife raus.
Also wird es letztlich auch nie die Watcher disposen, oder?
Korrigiert mich gerne
VG
Zitat von @Celiko:
Bin mir unsicher, ob ich falsch liege... aber das Script geht nie aus der While-Schleife raus.
Also wird es letztlich auch nie die Watcher disposen, oder?
Korrigiert mich gerne
Doch das ist schon richtig so, da ohne eine Schleife sich die Shell direkt wieder schließen würde und dadurch die Events nicht feuern könnten.Bin mir unsicher, ob ich falsch liege... aber das Script geht nie aus der While-Schleife raus.
Also wird es letztlich auch nie die Watcher disposen, oder?
Korrigiert mich gerne
Das sleep 1 kann man aber auch durch die WaitForChanged Methode ersetzen das ist noch etwas effizienter
https://learn.microsoft.com/de-de/dotnet/api/system.io.filesystemwatcher ...
Durch das TryCatch werden die Handler bei einem Abbruch der Schleife mit CTRL+C anschließend im finally Block der am Ende immer ausgeführt wird, disposed. Das ist aber nur notwendig wenn die Konsole danach noch offen bleibt denn ansonsten würden die Objekte samt Handler mit Events beim Schließen der PS-Konsole eh automatisch zerstört.
Ich gebe zu da jetzt erst einmal "Bahnhof" zu verstehen.
Nun der Action Skriptblock läuft in einem Event-Skriptblock der quasi separat ausgeführt wird und somit kennt der die Variablen die außerhalb von diesem Skriptblock deklariert wurden nicht. In deinem Fall ist das die Variable $verzeichnisse, die ist dann innerhalb des Blocks leer. Wenn du diese als $global:verzeichnisse deklarieren würdest wäre sie auch im Eventblock verfügbar. Da die Verwendung von $global aber schlechter Stil ist habe ich dir oben das Beispiel mit der Übergabe der Variable über den MessageData-Parameter gezeigt.Das löst dann auch gleich das ineffiziente ermitteln des Zeilpfades gleich mit
Die ISE gaukelt einem hier oft was vor weil die die Variablen am Ende nicht wieder löscht. Deswegen ist die ISE beim Entwickeln immer mit Vorsicht zu genießen.
Also einfach noch mal in Ruhe die Seiten lesen und meinen Beispielcode oben verstehen, ein Meister fällt ja nicht vom Himmel.
Lesen und Verstehen ist am Ende des Tages einfach nachhaltiger als mit Copy n Paste sich hier alles vorbeten zu lassen.