koaxman
Goto Top

Powershell: Ordner überwachen, Datei umbenennen und kopieren oder verschieben, per E-Mail senden

Hallo,
ich benötige etwas Hilfe, bzw. Vorschläge bei meinem Vorhaben.
Von hier habe ich mir zwei Scripte modifiziert, die auch unabhängig funktionieren, nun hätte ich das gerne in "einem einzigen" Script verpackt, das bekomme ich leider nicht hin.
Was soll passieren:
Monatlich (immer am 1. des Monats) wird eine .csv Datei vom vorherigen Monat generiert (Report.csv (Name immer gleich)) und in einem Ordner abgelegt (c:\Reports)
Diese Datei soll automatisch umbenannt werden, also am 1.Juni 2020 z.B. dementsprechend in "Report Mai 2020.csv"
Aktuell schaffe ich es nur das aktuelle Datum/Uhrzeit einzubauen.
Diese umbenannte Datei soll dann in den Ordner "c:\Reports\toEmail" verschoben oder kopiert werden und anschließend per Email versendet werden.

Mein angepasster Teil mit dem "per Email versenden" funktioniert einwandfrei, nur das mit dem umbenennen und kopieren leider noch nicht.

Vielleicht kann mir hierbei ein Spezialist unter die Arme greifen?
Mir fehlt da leider die praktische Erfahrung.

Vielen Dank im Voraus.

Hier meine Versuche:

umbenennen und kopieren funktioniert nicht
<#
    Monitors folder for new files and renames specific files
#>
# Variables -------------------------
# local folder path to monitor
    $localFolderPath = "c:\Reports"   
# interval to check for changes
    $intMonitorInterval = 2
# file pattern in folder to monitor
    $strFilePattern = "%.csv"  
# -----------------------------------

# get seperate drive and path for wql query specific formatting
$strDrive = $localFolderPath.Split("\")  
$localFolderPath.TrimEnd("\")  
$strPath = $localFolderPath.Split(":")[1].Replace("\","\\")+"\\"  

# action fired when event occurs
$eventaction = {
    #object which fired the event
    $obj = $Event.SourceEventArgs.NewEvent.TargetInstance
    
    #create reference to a wmi-Object to get access to a function which converts wmi-datetime-strings to .net DateTime-Object
    $objWMI = (gwmi -Class "Win32_Process")  
    $fileModifiedDate = $objWMI.ConvertToDateTime($obj.LastModified)
    #new filename
    $newName = "Report $(get-date $fileModifiedDate -Format 'dd.MM.yyyy HH.mm').csv"  
    #rename the file
    Rename-Item -Path $obj.Name -NewName $newName
    #write some info to the console
    write-host "Neue Datei im Ordner: '"$obj.Name"' wurde umbenannt in '"$newname"'"  
}

# WQL Query which monitors a folder every x seconds for a new file appearing with a specific filename
$query = "Select * From __InstanceCreationEvent WITHIN $intMonitorInterval`  
          where TargetInstance ISA 'CIM_DataFile'`  
          and TargetInstance.Drive = '$strDrive'`  
          and TargetInstance.Path = '$strPath'`  
          and TargetInstance.Name like '$strFilePattern'"  

#actually register Event-Subscriber
Register-WmiEvent -query $query -SourceIdentifier "Monitor Folder Watcher" -action $eventaction  

# to end monitoring the event, call
# Unregister-Event -SourceIdentifier "Monitor Folder Watcher"  


Email Versand funktioniert:
# Ordner der überwacht wird
$folder = 'C:\Reports\toEmail'  
# Dateifilter
$filter = '*.csv'  
# ---------
if ($PSVersionTable.PSVersion.Major -lt 3){write-host "ERROR: Minimum Powershell Version 3.0 is required!" -F Yellow; return}    

Unregister-Event -SourceIdentifier FileCreated -EA 0
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'}   

Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
    $fullpath = $Event.SourceEventArgs.FullPath
    $timeStamp = $Event.TimeGenerated
    Write-Host "Die Datei '$fullpath' wurde um '$timeStamp' erstellt. Sende E-Mail mit Attachment ..." -fore green -NoNewline  
    try{
        Send-MailMessage –To "xxx@gmx.de" -BCC "xxx@web.de" –Subject "xxx Report" –Body "xxx Report" –SmtpServer "xx.xxx.x.xx" –From "xxxreports@xxx.de" -Attachments $fullpath -EA Stop  
        write-host "OK." -F Green  
        # lösche Datei
        # remove-item $fullpath -Force
    }catch{
        write-host "Error: $($_.Exception.Message)" -f Red  
    }
}
cls
write-host "Warte auf neue Dateien im Ordner ..."  
while($true){sleep 1}

Content-Key: 576276

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

Printed on: April 26, 2024 at 04:04 o'clock

Member: manuel-r
manuel-r Jun 02, 2020 at 13:15:34 (UTC)
Goto Top
Monatlich (immer am 1. des Monats) wird eine .csv Datei vom vorherigen Monat generiert (Report.csv (Name immer gleich)) und in einem Ordner abgelegt (c:\Reports)

Ich habe mir die beiden Scripte noch nicht näher angesehen, aber ich hätte da schon eine Frage:
Das auslösende Ereignis findet genau einmal im Monat und zwar immer am Monatsersten statt. Vermutlich sogar immer um die gleiche Uhrzeit. Warum willst du das also über ein Event auslösen? Wäre es nicht einfacher das mit einem geplanten Task abzufackeln?

Manuel
Member: koaxman
koaxman Jun 02, 2020 at 13:33:24 (UTC)
Goto Top
Ich bin für jede Möglichkeit offen, die das gewünschte Ergebnis liefern kann face-wink
Richtig, immer am Monatsersten gegen 00:02 Uhr kommt eine neue Datei.
Mitglied: 144260
Solution 144260 Jun 02, 2020 updated at 13:39:51 (UTC)
Goto Top
Zitat von @manuel-r:
Warum willst du das also über ein Event auslösen? Wäre es nicht einfacher das mit einem geplanten Task abzufackeln?
Sehe ich genau so. Schon weil das nur einmal im Monat vorkommt dann ein Skript die ganze Zeit im Leerlauf rumwarten und Prozessor-Zeit verbraten lassen ist ja schon fast eine Sünde face-wink.

So lässt sich das ganze hierauf als monatlichen Task reduzieren
$folder = 'C:\Reports'  
$attachment = ls $folder -Filter *.csv -File | sort LastWriteTime -Desc | select -F 1 | rename-item -NewName {"Report $((get-date).AddMonths(-1).ToString('MMMM yyyy'))$($_.Extension)"} -PassThru  
if ($attachment){
    Send-MailMessage –To "xxx@gmx.de" -BCC "xxx@web.de" –Subject "xxx Report" –Body "xxx Report" –SmtpServer "xx.xxx.x.xx" –From "xxxreports@xxx.de" -Attachments $attachment.FullName -EA Stop  
    del $attachment.FullName
}
Member: manuel-r
Solution manuel-r Jun 02, 2020 at 13:57:58 (UTC)
Goto Top
Ich bin für jede Möglichkeit offen, die das gewünschte Ergebnis liefern kann

Dann vielleicht ungefähr so (ungetestet)
$Suchpfad = "c:\temp"  
$Ablagepfad = "c:\temp\email"  
$Suchdatei = "report.csv"  
$Zeitstempel = (Get-Date -Format "dd-MM-yyyy").ToString()  

if (!(Test-Path $Suchpfad)) {
	Exit
}

if (!(Test-Path $Ablagepfad)) {
	New-Item -Path $Suchpfad -Name "email" -Type Directory  
}

if (Test-Path ($Suchpfad + "\" + $Suchdatei)) {  
	Move-Item -Path ($Suchpfad + "\" + $Suchdatei) -Destination ($Ablagepfad + "\" + "report_" + $Zeitstempel + ".csv")  
	Send-MailMessage –To "xxx@gmx.de" -BCC "xxx@web.de" –Subject "xxx Report" –Body "xxx Report" –SmtpServer "xx.xxx.x.xx" –From "xxxreports@xxx.de" -Attachments ($Ablagepfad + "\" + "report_" + $Zeitstempel + ".csv")  
} else {
	Write-Host "Datei nicht gefunden"  
}
Das Script dann um 00:10 Uhr am Monatsersten ausführen. Um zu verhindern, dass die eMail nicht verschickt wird, wenn der Quellprozess mal später kommt würde ich das Script ab 00:10 eine Stunde lang alle 5 Minuten laufen lassen. Das sollte dann in aller Regel wohl hinhauen.

Manuel
Member: koaxman
koaxman Jun 02, 2020 updated at 14:35:08 (UTC)
Goto Top
Ich bin beeindruckt und begeistert wie schnell das hier läuft!!
Das Script funktioniert bestens!!
Vielen Dank schon mal!
Eine Kleinigkeit noch: Die umbenannte Datei würde ich gerne nach dem Versand in einen anderen Ordner (c:\Reports\old) verschieben und nicht löschen wollen.
Move-Item ... ?
Ich weiß gerade nicht wie ich das mit der Variable ($attachment) mache?
Danke vorab!!

Edit: Das geht ja Schlag auf Schlag hier, komme gar nicht hinterher face-smile
Mein Post hier bezog sich auf das Script von "killpid"

Das von "manuel" habe ich noch nicht probiert - trotzdem danke!
Mitglied: 144260
Solution 144260 Jun 02, 2020 updated at 14:58:11 (UTC)
Goto Top
Zitat von @koaxman:
Eine Kleinigkeit noch: Die umbenannte Datei würde ich gerne nach dem Versand in einen anderen Ordner (c:\Reports\old) verschieben und nicht löschen wollen.
Move-Item ... ?
Ich weiß gerade nicht wie ich das mit der Variable ($attachment) mache?
Danke vorab!!
Statt
del $attachment.FullName
$attachment | move-item -Destination "D:\Archiv" -Force
Member: koaxman
koaxman Jun 02, 2020 at 15:10:25 (UTC)
Goto Top
Perfekt!
Funktioniert bestens!
Vielen Dank an alle für die schnelle und kompetente Hilfe!