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-Key: 604571

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

Printed on: April 25, 2024 at 14:04 o'clock

Member: TK1987
TK1987 Sep 14, 2020 updated at 13:00:21 (UTC)
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
Member: GreeeNn
GreeeNn Sep 14, 2020 at 13:17:53 (UTC)
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%'"  
	
	)
	
Member: TK1987
TK1987 Sep 14, 2020 at 13:52:27 (UTC)
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.
Member: miniversum
miniversum Sep 14, 2020 at 15:21:17 (UTC)
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ß
...
Member: erikro
erikro Sep 14, 2020 updated at 16:12:57 (UTC)
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>
Member: GreeeNn
GreeeNn Sep 15, 2020 at 06:14:37 (UTC)
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
Member: GreeeNn
GreeeNn Sep 15, 2020 at 06:17:41 (UTC)
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!
Member: GreeeNn
GreeeNn Sep 15, 2020 at 07:17:24 (UTC)
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!
Member: erikro
Solution erikro Sep 15, 2020, updated at Sep 17, 2020 at 14:40:58 (UTC)
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
Member: erikro
erikro Sep 15, 2020 at 18:54:59 (UTC)
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
Member: miniversum
Solution miniversum Sep 17, 2020 at 04:22:35 (UTC)
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ß
...
Member: GreeeNn
GreeeNn Sep 17, 2020 at 13:16:00 (UTC)
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!
Member: erikro
erikro Sep 17, 2020 at 14:41:55 (UTC)
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.
Member: GreeeNn
GreeeNn Oct 23, 2020 at 13:56:55 (UTC)
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"  

	 }