Powershell-Ordnermonitor/Batchausführung

Powershell-Ordnermonitor/Batchausführung

Ich bin neu bei Powershell. Ich habe ein Skript gefunden, das mehr oder weniger mit meinen Anforderungen funktioniert.

Ich suche nach einem Skript, das einen Ordner auf bestimmte Dateinamen/-typen überwacht. Je nach Dateiname/-typ soll es eine bestimmte Batchdatei ausführen, um einen Befehl für ein Serverdienstprogramm auszuführen.

Wie genau würde ich das erreichen? Ich habe dieses Skript gefunden und ein Aufrufelement hinzugefügt, um eine Bat-Datei zu starten, wenn eine Datei wie PDF im Ordner landet. Ich muss es jedoch filtern und es je nach Dateinamen eine andere Bat-Datei starten lassen. Was ich derzeit habe, ruft die Bat-Datei für jede Datei auf, die im Ordner landet, was ich nicht will. Mein Wissen ist minimal und ich weiß nur genug, um gefährlich zu sein.

Wenn XXXX.PDF, XXRX.PDF, XXLX.PDF den Ordner erreichen, muss ich wissen, dass nur XXXX.bat ausgeführt wird, wenn XXXX.PDF landet. Wenn XXRX.PDF landet, wird nur XXRX.BAT ausgeführt usw. usw.

### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "D:\XXXX\XXXX"
    $watcher.Filter = "*.PDF"
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true 

### DEFINE ACTIONS AFTER A EVENT IS DETECTED

    $action = {Invoke-Item "D:\BATCH FILES\XXXXX.bat" -filter = "XXXXX.pdf"}    

### DECIDE WHICH EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY  
    $created = Register-ObjectEvent $watcher "Created" -Action $action
###    $changed = Register-ObjectEvent $watcher "Changed" -Action $action
###    $deleted = Register-ObjectEvent $watcher "Deleted" -Action $action
###    $renamed = Register-ObjectEvent $watcher "Renamed" -Action $action
    while ($true) {sleep 5}

Antwort1

FileWatcher haben Macken,abhängig davon, wie Dateien erstellt werden:

In bestimmten Situationen stellen Sie möglicherweise fest, dass ein einzelnes Erstellungsereignis mehrere „Created“-Ereignisse generiert, die von Ihrer Komponente verarbeitet werden. Wenn Sie beispielsweise eine FileSystemWatcher-Komponente verwenden, um die Erstellung neuer Dateien in einem Verzeichnis zu überwachen, und diese dann testen, indem Sie mit Notepad eine Datei erstellen, werden möglicherweise zwei „Created“-Ereignisse generiert, obwohl nur eine einzige Datei erstellt wurde. Dies liegt daran, dass Notepad während des Schreibvorgangs mehrere Dateisystemaktionen ausführt. Notepad schreibt in Stapeln auf die Festplatte, die den Inhalt der Datei und dann die Dateiattribute erstellen. Andere Anwendungen können auf die gleiche Weise vorgehen. Da FileSystemWatcher die Betriebssystemaktivitäten überwacht, werden alle Ereignisse, die diese Anwendungen auslösen, erfasst.

Hinweis: Notepad kann auch andere interessante Ereignisgenerierungen verursachen. Wenn Sie beispielsweise mit ChangeEventFilter angeben, dass Sie nur auf Attributänderungen achten möchten, und dann mit Notepad in eine Datei im überwachten Verzeichnis schreiben, wird ein Ereignis ausgelöst. Dies liegt daran, dass Notepad während dieses Vorgangs das Archived-Attribut für die Datei aktualisiert.

In Ihrem Fall würde ich also einen einfachen Verzeichnisvergleich durchführen. Hier ist das Skript, das das Verzeichnis auf Änderungen überwacht und Dateien ausführt. Speichern Sie dieses Skript unter MonitorAndExecute.ps1. Es akzeptiert folgende Argumente:

  • Weg:zu überwachender Ordner. Wenn nicht angegeben, wird das aktuelle Verzeichnis verwendet.
  • Filter:Dateierweiterung, die übereinstimmen soll. Der Standardwert ist *, d. h., alle Dateien werden übereinstimmen.
  • Laufen:Dateierweiterung, die ausgeführt werden soll, wenn eine neue Datei gefunden wird. Standard ist bat.
  • Rekurs:Verzeichnisse rekursiv verwenden oder nicht. Der Standardwert ist „false“.
  • Intervall:Ruhezeit in Sekunden zwischen Ordnerscans. Der Standardwert ist 5Sekunden.
  • Ausführlich:Das Skript informiert Sie über Nachrichten darüber, was passiert Write-Verbose.

Beispiel (von der PowerShell-Konsole aus ausführen).

Überwachen Sie *.pdfdie Dateien im Ordner D:\XXXX\XXXX, gehen Sie rekursiv vor, wenn die neue Datei gefunden wird, führen Sie die Datei mit demselben Basisnamen und derselben Erweiterung aus *.batund seien Sie ausführlich:

.\MonitorAndExecute.ps1 -Path 'D:\XXXX\XXXX' -Filter '*.pdf' -Run 'bat' -Recurse -Interval 10 -Verbose

MonitorAndExecute.ps1Skript:

Param
(
    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [ValidateScript({
        if(!(Test-Path -LiteralPath $_ -PathType Container))
        {
            throw "Input folder doesn't exist: $_"
        }
        $true
    })]
    [ValidateNotNullOrEmpty()]
    [string]$Path = (Get-Location -PSProvider FileSystem).Path,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [string]$Filter = '*',

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [string]$Run = 'bat',

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [switch]$Recurse,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [int]$Interval = 5
)

# Scriptblock that gets list of files
$GetFileSet = {Get-ChildItem -LiteralPath $Path -Filter $Filter -Recurse:$Recurse | Where-Object {!($_.PSIsContainer)}}

Write-Verbose 'Getting initial list of files'
$OldFileSet = @(. $GetFileSet)
do
{
    Write-Verbose 'Getting new list of files'
    $NewFileSet = @(. $GetFileSet)

    Write-Verbose 'Comaparing two lists using file name and creation date'
    Compare-Object -ReferenceObject $OldFileSet -DifferenceObject $NewFileSet -Property Name, CreationTime -PassThru |
        # Select only new files
        Where-Object { $_.SideIndicator -eq '=>' } |
            # For each new file...
            ForEach-Object {
                Write-Verbose "Processing new file: $($_.FullName)"
                # Generate name for file to run
                $FileToRun = (Join-Path -Path (Split-Path -LiteralPath $_.FullName) -ChildPath ($_.BaseName + ".$Run"))

                # If file to run exists
                if(Test-Path -LiteralPath $FileToRun -PathType Leaf)
                {
                    Write-Verbose "Running file: $FileToRun"
                    &$FileToRun
                }
                else
                {
                    Write-Verbose "File to run not found: $FileToRun"
                }
            }

    Write-Verbose 'Setting current list of files as old for the next loop'
    $OldFileSet = $NewFileSet

    Write-Verbose "Sleeping for $Interval seconds..."
    Start-Sleep -Seconds $Interval
}
while($true)

verwandte Informationen