Ich muss bei jeder Erstellung einer Datei einen Ordner überwachen und Aktionen ausführen. Ich habe 2 Lösungen - einen WMI verwenden, wo ich diese Filter verwenden kann (so genannten entweder von einer .MOF
Datei oder einem Skript Powershell, die permanent MWI Ereignisbindungen registriert) den Ordner in jeder Sekunde abzufragen:Die effizienteste und zuverlässigste Möglichkeit, die Dateierstellung in einem bestimmten Ordner dauerhaft zu überwachen
SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA "Cim_DirectoryContainsFile" AND TargetInstance.GroupComponent="Win32_Directory.Name='C:\\test'"
Beispielskript :
$query = @"
SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA "Cim_DirectoryContainsFile" AND TargetInstance.GroupComponent="Win32_Directory.Name='C:\\test'"
"@
#Set up hash table for splatting
$wmiParams = @{
Computername = $env:COMPUTERNAME
ErrorAction = 'Stop'
NameSpace = 'root\subscription'
}
######################################################################################################################### Filter
#Creating a new event filter
$wmiParams.Class = '__EventFilter'
$wmiParams.Arguments = @{
Name = 'WatchFiles'
EventNamespace = 'root\CIMV2'
QueryLanguage = 'WQL'
Query = $query
}
$filterResult = Set-WmiInstance @wmiParams
######################################################################################################################### Consumer
$wmiParams.Class = 'ActiveScriptEventConsumer'
$wmiParams.Arguments = @{
KillTimeout = 0
MachineName = $env:COMPUTERNAME
ScriptingEngine = 'VBScript'
ScriptText =
@"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("c:\test\Log.log", 8, True)
objFile.WriteLine "hellohellohellohellohellohello"
objFile.Close
"@
ScriptFileName = $null
Name = 'ActiveScriptEventConsumer'
}
$consumerResult = Set-WmiInstance @wmiParams
######################################################################################################################### Binding
$wmiParams.Class = '__FilterToConsumerBinding'
$wmiParams.Arguments = @{
Filter = $filterResult
Consumer = $consumerResult
}
$bindingResult = Set-WmiInstance @wmiParams
Beispiel MOF-Datei:
#PRAGMA AUTOREOVER
#pragma namespace("\\\\.\\root\\subscription")
instance of __EventFilter as $EventFilter
{
Name = "Event Filter Instance Name";
EventNamespace = "Root\\Cimv2";
Query = "Select * From __InstanceCreationEvent Within 1 "
"Where TargetInstance Isa \"Cim_DirectoryContainsFile\" "
"and TargetInstance.GroupComponent=\"Win32_Directory.Name=\'C:\\\\test\'\"";
QueryLanguage = "WQL";
};
instance of ActiveScriptEventConsumer as $Consumer
{
Name = "TestConsumer";
ScriptingEngine = "VBScript";
ScriptFileName = "C:\\test\\test.vbs"
};
instance of __FilterToConsumerBinding
{
Filter = $EventFilter;
Consumer = $Consumer;
};
Dies scheint eine gute Möglichkeit zu sein, da ich das Intervall selbst einstellen kann, und die Arbeit mit WMI fühlt sich für mich immer sicher an, da es eine eingebaute Lösung in Windows ist.
Ein anderer Weg, dies zu tun, wäre ein Skript zu schreiben, so etwas wie:
$folderpath = 'C:\test'
$items = Get-ChildItem $folderpath
$currentdatetime = Get-Date
foreach($item in $items) {
If ($item.CreationTime > $currentdatetime.AddSeconds(-5)){
# Do some action
}
}
, die dann auf dem System als eine geplante Aufgabe ausgeführt werden kann.
Meine Frage ist - was ist der beste Weg, dies zu tun? Von den 2 Möglichkeiten, die ich gezeigt habe, ist eine von ihnen von Natur aus effizienter in Bezug auf Systemressourcen oder das Potenzial für Fehler?
Gibt es andere Möglichkeiten, dies zu tun, die ich nicht berücksichtigt habe?
Jisaak hat eine Antwort hinzugefügt, die System.IO.FilesystemWatcher
verwendet. Leider ist dies nicht ideal für meine Zwecke, da dies nur funktioniert, während die Shell, die es ausgeführt hat, offen ist, während ich eine dauerhafte Lösung möchte (aktualisiert den Titel der Frage, um dies zu reflektieren)
HI Jisaak danke für Ihre Antwort. Warum ist die Verwendung von 'FileSystemWatcher' eine bessere Lösung? Dazu müsste auch eine geplante Aufgabe eingerichtet werden. Bedeutet dies nicht, dass mehr Wartung erforderlich ist? Was sind die Vorteile, wenn man so vorgeht, und was ist falsch beim langen Polling eines Ordners? Sicherlich könnte ich einfach in meine Aktionsskript für meine permanente Ereignisregistrierung aufnehmen, um eine E-Mail zu senden oder mich auf irgendeine Weise zu benachrichtigen, ohne 'FileSystemWatcher' zu benötigen. Nochmals vielen Dank für die Hilfe! – Bassie
Nun, ich habe nichts zur Performance recherchiert, aber ich denke, dass dies der effizienteste Weg ist, Änderungen in einem Verzeichnis zu verfolgen. Lange Umfragen sind wie immer das Schlimmste, was man tun kann. –
Danke jisaak. Ich hätte erwähnen sollen, dass ich bereits eine ähnliche Methode benutzt habe, bei der ich mich für ein Event in der Shell anmelde. Leider ist dies nicht ideal, da es nur dauert, während die Shell, die das Skript ausgeführt hat, geöffnet bleibt. Die Lösungen, die ich oben gepostet habe, registrieren beide einen permanenten Ereignisfilter (der auch dann weiterläuft, wenn der PC neu gestartet wird), weshalb ich mir diese Methoden ansehe. Ich habe meine Frage aktualisiert, um diese Anforderung zu berücksichtigen. – Bassie