greeenn
Goto Top

Ordner mit .bat überwachen

Hallo,

vielleicht kann mir hier jemand weiterhelfen.

Ich möchte einen Ordner mit einer Batch Datei überwache diese soll jede Stunde über die Windows Aufgabenplanung mit Administrativen Rechten gestartet werden.
Die Batch Datei soll einen Ordner überwachen in dem PDF Dateien landen.
Die Dateien werden eigentlich automatisch verschoben jedoch bleiben ab und zu ein paar Dateien hängen.

Aus diesem Grund soll die Batch das Änderungsdatum von allen Dateien die sich zu dieser Zeit im Ordner befinden überprüfen und mit der aktuellen Zeit vergleichen.
Sollte bei einer Datei das Änderungsdatum älter als eine Stunde sein, so weiß die Batch das die Datei nicht automatisch weiter verschoben wurde.
In diesem Fall soll eine Email verschickt werden die diese Information enthält.

Das ganze Funktioniert bei mir schon ganz Gut ich bekomme es nur irgendwie nicht hin die Uhrzeit des Änderungsdatums auszulesen.

Kann mir jemand dazu einen Tipp geben?


Liebe Grüße und vielen Dank im voraus!

Content-ID: 604571

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

Ausgedruckt am: 23.11.2024 um 12:11 Uhr

TK1987
TK1987 14.09.2020 aktualisiert um 15:00:21 Uhr
Goto Top
Moin,

Zitat von @GreeeNn:
Die Dateien werden eigentlich automatisch verschoben jedoch bleiben ab und zu ein paar Dateien hängen.
Ich würde in dem Fall eher mal prüfen, wieso diese Dateien hängen bleiben.
Ich möchte einen Ordner mit einer Batch Datei überwache diese soll jede Stunde über die Windows Aufgabenplanung mit Administrativen Rechten gestartet werden.
Die Batch Datei soll einen Ordner überwachen in dem PDF Dateien landen.
Wieso mit Administrativen Rechten?! Sieht mir nicht danach aus, das diese erforderlich wären.
Aus diesem Grund soll die Batch das Änderungsdatum von allen Dateien die sich zu dieser Zeit im Ordner befinden überprüfen und mit der aktuellen Zeit vergleichen.
Mit Batch kaum zu Realisieren, oder man muss schon extrem masochistisch veranlagt sein.

Mit Powershell ein leichtes, jedoch wäre es hier sinnvoller, die gewünschten Aktionen direkt auszuführen, wenn etwas beim verschieben falsch läuft. In jedem Fall besser, als den Ordner zu überwachen.

Mein Vorschlag hier wäre, du postest uns mal dein Batch-Skript, welches die PDF-Dateien verschiebt; und wir schreiben dir das als Powershell-Skript um, damit weiterer Ärger ausbleibt.

Gruß Thomas
GreeeNn
GreeeNn 14.09.2020 um 15:17:53 Uhr
Goto Top
Hi,

danke schon mal für deine Antwort.

Die Dateien werden eigentlich automatisch verschoben jedoch bleiben ab und zu ein paar Dateien hängen.
Ich würde in dem Fall eher mal prüfen, wieso diese Dateien hängen bleiben.

Hab ich schon versucht aber keine Lösung daür gefunden, deswegen wollte ich das Script dazu schalten.

Ich möchte einen Ordner mit einer Batch Datei überwache diese soll jede Stunde über die Windows Aufgabenplanung mit Administrativen Rechten gestartet werden.
Die Batch Datei soll einen Ordner überwachen in dem PDF Dateien landen.
Wieso mit Administrativen Rechten?! Sieht mir nicht danach aus, das diese erforderlich wären.

Am Ende der Batch wird die Powershell mit SendmailMessage aufgerufen um die Email zu verschicken. Dafür werden die Administrativen Rechte benötigt.

Mein aktueller Code Funktioniert Perfekt, jedoch prüft er auf das Datum und nicht auf die Uhrzeit.

Ein paar Sachen musste ich durch "XXX" ersetzen, diese sind nicht zu beachten.

PS:

Ich bin nicht sonderlich geübt mit Batch Scripting also falls du gleich die Hände über dem Kopf zusammenschlägst^^

@echo off & setlocal EnableDelayedExpansion

REM Variabeln 
SET "Typ=pdf"  
SET "Verzeichnis=" REM Pfad des zu überwachenden Ordners eintragen  
SET "Heute=%date%"  
SET "Datei="  

REM Variabeln für den Email versand
SET "SendMail=0"  
SET "SMTP=XXX"  
SET "SUBJECT=XXX"  
SET BODY="^<html^>^<body^>"  
SET "FROM=XXX"  
SET "TO=XXX"  


cd %Verzeichnis% || goto :eof


for %%i in ("*.%Typ%") do (  
   
	SET Datei=%%i
	SET Data=%Datei%
	SET Datum=%%~ti 
	
    SET Datum=!Datum:~,-6!
    
    echo Datei: !Datei! mit Datum: !Datum!

    if !Heute! NEQ !Datum! (

		SET SendMail=1
		SET "BODY=!BODY!!Datei!"  
		SET "BODY=!BODY!^<br^>"  
    ) 
	
)


set BODY = %BODY% "^</body^>^</html^>"  


if !SendMail! == 1 (
	
		powershell -ExecutionPolicy Unrestricted -c  "Send-MailMessage -BodyAsHtml -To '%TO%' -Subject '%SUBJECT%' -Body '%BODY%' -SmtpServer '%SMTP%' -From '%FROM%'"  
	
	)
	
TK1987
TK1987 14.09.2020 um 15:52:27 Uhr
Goto Top
Das ist ein Skript zum überwachen des Ordners. Wie bereits erwähnt, bitte das Skript posten, welches die PDF-Dateien verschiebt.

Das Ziel sollte hier sollte sein: Das Skript veruscht die Dateien zu verschieben, falls dies (warum auch immer) fehlschlägt, wird eine E-Mail mit Details zu dem Fehler rausgeschickt. Damit ist ein zweites Skript welches den Ordner überwacht überflüssig.
miniversum
miniversum 14.09.2020 um 17:21:17 Uhr
Goto Top
Hallo,

Die Batch stimmt schon fast. Da ist nur ein kleiner Fehler drin der die Ausführung verhindert.
Batch kentn das Format "Datum" nicht, nur Zahlen.
Deshalb musst du einfach dein Datum von %%~ti und von heute im Format YYYMMDD ist, also nur anders zusammengesetzt. Dann klappt das "if !Heute! NEQ !Datum!" auch.

Der Aufwand hällt sich also doch in Grenzen...

Gruß
...
erikro
erikro 14.09.2020 aktualisiert um 18:12:57 Uhr
Goto Top
Moin,

oder halt einfach mit der Powershell in einer Zeile:

Get-ChildItem *.pdf | %{if($_.LastWriteTime -lt (get-date).addhours(-1)){ Send-MailMessage ...}}

hth

Erik

<edit>Ooops, da fehlte eine Klammer.</edit>
GreeeNn
GreeeNn 15.09.2020 um 08:14:37 Uhr
Goto Top
Moin ,

danke schon mal für den Tipp!

Wie oben schon erwähnt ist das der jetzige stand wo auf das Datum geprüft wird.

Deshalb musst du einfach dein Datum von %%~ti und von heute im Format YYYMMDD ist, also nur anders zusammengesetzt. Dann klappt das "if !Heute! NEQ !Datum!" auch.

In der neuen Version würde ich aber lieber die aktuelle Systemzeit mit dem Änderungsdatum der Datei vergleichen.
Sprich wenn die Uhrzeit die im änderungsdatum steht, älter als eine Stunde ist schicke eine Email.

Irgendwelche Tipps dazu?


Beste Grüße
GreeeNn
GreeeNn 15.09.2020 um 08:17:41 Uhr
Goto Top
Hey,

danke für deinen Lösungsansatz @erikro!

> Get-ChildItem *.pdf | %{if($_.LastWriteTime -lt (get-date).addhours(-1)){ Send-MailMessage ...}}
> 

Könntest du den Code weiter ausführen oder bisschen erklären?
Mit Powershell habe ich ebenso wenig Erfahrung.

Vielen Dank und Grüße!
GreeeNn
GreeeNn 15.09.2020 um 09:17:24 Uhr
Goto Top
Moin,

Das Ziel sollte hier sollte sein: Das Skript veruscht die Dateien zu verschieben, falls dies (warum auch immer) fehlschlägt, wird eine E-Mail mit Details zu dem Fehler rausgeschickt. Damit ist ein zweites Skript welches den Ordner überwacht überflüssig.

Natürlich wäre es der Optimalfall das Skript das die Daten verschieb zu verbessern.
Jedoch habe ich die Anweisung bekommen diese Überwachung einzurichten, da der fall das die Daten nicht verschoben werden relativ selten eintritt.

Viele Grüße!
erikro
Lösung erikro 15.09.2020, aktualisiert am 17.09.2020 um 16:40:58 Uhr
Goto Top
Moin,

Zitat von @GreeeNn:
danke für deinen Lösungsansatz @erikro!

>> Get-ChildItem *.pdf | %{if($_.LastWriteTime -lt (get-date).addhours(-1)){ Send-MailMessage ...}}
>> 


Wenn Du so lieb fragst. face-wink

PARAM(

    $typ="pdf",  
    $path, # Pfad des zu überwachenden Ordners eintragen
    $time= (get-date).addhours(-1), # Holt das aktuelle Datum mit Zeit und zieht eine Stunde ab

    # Variabeln für den Emailversand
    $SMTP=XXX,
    $SUBJECT=XXX,
    $BODY,
    $FROM="XXX",  
    $TO="XXX"  
    # Im PARAM-Block stehen alle Parameter eines Skripts, die dann wie in der
    # PS üblich mit -variablenname dem Skript übergeben werden. Also z. B.
    # dein_skript-ps1 -typ doc -path $env:userprofile\Documents.
    # Wird im PARAM-Block einem Parameter ein Wert zugewiesen, dann ist das der default.
    # Die Parameter werden mit Kommata getrennt. Nach dem letzten darf (leider) kein Komma stehen.
)

$files = get-childitem $path\*.pdf # Liest alle Dateiobjekte, die PDFs sind, 
                                   # in das array $files ein. 
                                   # -recurse, falls Unterverzeichnisse
                                   # mit durchsucht werden sollen.
 
foreach($file in $files) { # Für jedes Element des Arrays $files, das wir in der Schleife $file nennen

      if($file.LastWriteTime -lt $time) { # Wenn die Eigenschaft des LastWriteTime des Objekts kleiner ist als $time

                 # Schicke die Mail
                 send-mailmessage ...

     }

}

Ist jetzt nicht mehr eine Zeile, aber so würde ich das als Skript schreiben. Ist übersichtlicher und schneller als der Einzeiler.

Und jetzt noch ein paar Worte zum Einzeiler:

1. Eine der wichtigsten Techniken der Powershell vor allem auf der Konsole ist die Pipe (|). Dabei wird die Ausgabe eines Befehls als Stream dem nächsten Befehl übergeben. Sehr praktisch.
2. % ist eine Abkürzung (ein Alias genau gesagt) für foreach-object.
3. $_ ist die Variable, in der das Objekt steht aus der Pipe, das gerade dran ist.

hth

Erik
erikro
erikro 15.09.2020 um 20:54:59 Uhr
Goto Top
Moin,

Zitat von @GreeeNn:
Natürlich wäre es der Optimalfall das Skript das die Daten verschieb zu verbessern.
Jedoch habe ich die Anweisung bekommen diese Überwachung einzurichten, da der fall das die Daten nicht verschoben werden relativ selten eintritt.

Dann rücke doch mal das Skript raus. Meine Glaskugel sagt mir nämlich folgendes:

Das Skript sieht so aus:

# Mache irgendwas mit dem PDF. Drucken vielleicht.
# Warte ein paar Sekunden
# Verschiebe das PDF

Und dann haben wir eine race condition. Dauert das, was da gemacht wird, zu lange, wird schon der Verschiebebefehl ausgeführt, der aber gegen die Wand läuft, weil noch ein lock auf der Datei ist. Besser wäre so ein Konstrukt:

# Mache was mit dem PDF
while(#prüfung, ob das PDF gelockt ist) {
    #Warte
}
# Verschiebe das PDF

Liebe Grüße

Erik
miniversum
Lösung miniversum 17.09.2020 um 06:22:35 Uhr
Goto Top
Hallo,

Wenn du die Zeit vergleichen willst dann nimm für heute halt %time% statt %date% oder noch besser beides und in der for Schleife in Zeile 21 holst du dir dann beides raus.
Das Prinzip ist das selbe nur halt im Format YYMMTThhmmss. Das aufaddieren von 1 Stunde mit Berücksichtigung des Datums geht in Batch (wurde hier auch schon mal beschrieben), ist aber mit einem gewissen Aufwand verbunden. Da wäre dann eine andere Skriptsprache, zumindest teilweise, doch besser geeignet.

Gruß
...
GreeeNn
GreeeNn 17.09.2020 um 15:16:00 Uhr
Goto Top
Hey vielen Danke schon mal für die gute Erklärung @erikro!

Ich bin gerade dabei dein Powershell Skript auf meine Anforderungen anzupassen dabei ist mir ein kleiner Fehler aufgefallen den ich gerne verbesser würde.

$typ="pdf",
$path, # Pfad des zu überwachenden Ordners eintragen
$time= (get-date).addhour(-1), # Holt das aktuelle Datum mit Zeit und zieht eine Stunde ab

.addhour muss durch .addhours ersetzt werden da anstonsten ein Fehler kommt.

So ist es zumindest bei mir.


Viele Grüße!
erikro
erikro 17.09.2020 um 16:41:55 Uhr
Goto Top
Zitat von @GreeeNn:

Hey vielen Danke schon mal für die gute Erklärung @erikro!

Gerne.


Ich bin gerade dabei dein Powershell Skript auf meine Anforderungen anzupassen dabei ist mir ein kleiner Fehler aufgefallen den ich gerne verbesser würde.

$typ="pdf",
$path, # Pfad des zu überwachenden Ordners eintragen
$time= (get-date).addhour(-1), # Holt das aktuelle Datum mit Zeit und zieht eine Stunde ab

.addhour muss durch .addhours ersetzt werden da anstonsten ein Fehler kommt.

Oooops. Ja, es muss der Plural sein. Ich habe es oben korrigiert. Danke für den Hinweis.
GreeeNn
GreeeNn 23.10.2020 um 15:56:55 Uhr
Goto Top
Hallo,

für alle die nach der Finalen Lösung suchen hier nochmal der Finale Code.

PARAM(

	# Allgemeine Variabeln
        $typ="pdf", 					                 #Datei Format  
        $time=(get-date).AddHours(-1), 		                         # Holt das aktuelle Datum mit Zeit und zieht eine Stunde ab
	$Dat_Gefunden="0",					         # Wenn Dateien die älter als eine Stunde sind gefunden werden wird der Wert zu   
	$carriage_return="<br>",					 # Hilfsvariable für Email Body  
	
	# Pfad Variabeln | Pfad des zu überwachenden Ordners eintragen
	$path1="", 			  
	$path2="",   
	$path3="",    
	$path4="", 	  
	$path5="", 	  
	$path6="", 		  

    # Variabeln für den Emailversand
    $SMTP="",						        # SMTP Server  
    $SUBJECT="",					        # Email Supject  
    $BODY="<html><body><br><br>", 	                        # Email Body  
    $FROM="",						        # Versandadresse  
    $TO=""							# Empfänger  
	
	
	
	
    
)
	
#Überwachung $path1

$files = get-childitem $path1\*.pdf     # Liest alle Dateiobjekte, die TXTs sind, 
                                        # in das array $files ein. 
                                        # -recurse, falls Unterverzeichnisse
                                        # mit durchsucht werden sollen.
 
foreach($file in $files) {              # Für jedes Element des Arrays $files, das wir in der Schleife $file nennen

    if($file.LastWriteTime -lt $time) { # Wenn die Eigenschaft des LastWriteTime des Objekts kleiner ist als $time
				
				$Dat_Gefunden="1"  
				$Body = $Body + $file + $carriage_return
     }

}
	$Body = $Body + $carriage_return + $carriage_return




#Überwachung $path2
	
$files = get-childitem $path2\*.pdf     # Liest alle Dateiobjekte, die PDFs sind, 
                                        # in das array $files ein. 
                                        # -recurse, falls Unterverzeichnisse
                                        # mit durchsucht werden sollen.
 
foreach($file in $files) {              # Für jedes Element des Arrays $files, das wir in der Schleife $file nennen

    if($file.LastWriteTime -lt $time) { # Wenn die Eigenschaft des LastWriteTime des Objekts kleiner ist als $time
				
				$Dat_Gefunden="1"  
				$Body = $Body + $file + $carriage_return
     }

}
	$Body = $Body + $carriage_return + $carriage_return




#Überwachung $path3

$files = get-childitem $path3\*.pdf     # Liest alle Dateiobjekte, die PDFs sind, 
                                        # in das array $files ein. 
                                        # -recurse, falls Unterverzeichnisse
                                        # mit durchsucht werden sollen.
 
foreach($file in $files) {              # Für jedes Element des Arrays $files, das wir in der Schleife $file nennen

    if($file.LastWriteTime -lt $time) { # Wenn die Eigenschaft des LastWriteTime des Objekts kleiner ist als $time
				
				$Dat_Gefunden="1"  
				$Body = $Body + $file + $carriage_return
     }

}
	$Body = $Body + $carriage_return + $carriage_return





#Überwachung $path4

$files = get-childitem $path4\*.pdf     # Liest alle Dateiobjekte, die PDFs sind, 
                                        # in das array $files ein. 
                                        # -recurse, falls Unterverzeichnisse
                                        # mit durchsucht werden sollen.
 
foreach($file in $files) {              # Für jedes Element des Arrays $files, das wir in der Schleife $file nennen

    if($file.LastWriteTime -lt $time) { # Wenn die Eigenschaft des LastWriteTime des Objekts kleiner ist als $time
				
				$Dat_Gefunden="1"  
				$Body = $Body + $file + $carriage_return
     }

}
	$Body = $Body + $carriage_return + $carriage_return





#Überwachung $path5

$files = get-childitem $path5\*.pdf     # Liest alle Dateiobjekte, die PDFs sind, 
                                        # in das array $files ein. 
                                        # -recurse, falls Unterverzeichnisse
                                        # mit durchsucht werden sollen.
 
foreach($file in $files) {              # Für jedes Element des Arrays $files, das wir in der Schleife $file nennen

    if($file.LastWriteTime -lt $time) { # Wenn die Eigenschaft des LastWriteTime des Objekts kleiner ist als $time
				
				$Dat_Gefunden="1"  
				$Body = $Body + $file + $carriage_return
     }

}
	$Body = $Body + $carriage_return + $carriage_return





#Überwachung $path6

$files = get-childitem $path6\*.pdf     # Liest alle Dateiobjekte, die PDFs sind, 
                                        # in das array $files ein. 
                                        # -recurse, falls Unterverzeichnisse
                                        # mit durchsucht werden sollen.
 
foreach($file in $files) {              # Für jedes Element des Arrays $files, das wir in der Schleife $file nennen

    if($file.LastWriteTime -lt $time) { # Wenn die Eigenschaft des LastWriteTime des Objekts kleiner ist als $time
				
				$Dat_Gefunden="1"  
				$Body = $Body + $file + $carriage_return
     }

}
	$Body = $Body + $carriage_return + $carriage_return




	if($Dat_Gefunden -eq "1") { #Wenn Dat_Gefunden ungleich(-eq) "1"  

			$Body = $Body + "</body></html>" # HTML Tags werden geschlossen  
		
			Send-MailMessage -BodyAsHtml -To "max@mustermann.com" -Subject "Muster" -Body $Body -SmtpServer "SMTP SERVER" -From "Versandadresse"  

	 }