Мне нужно следить за папкой и выполнять какое-либо действие каждый раз, когда создается файл. У меня есть 2 решения - один с помощью WMI, где я могу использовать этот фильтр (так называемый либо из .MOF
файла или сценарий Powershell, который регистрирует постоянные привязки событий MWI) опрашивать папку каждую секунду:Самый эффективный и надежный способ постоянного мониторинга создания файла в конкретной папке
SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA "Cim_DirectoryContainsFile" AND TargetInstance.GroupComponent="Win32_Directory.Name='C:\\test'"
Пример сценария :
$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
Пример MOF Файл:
#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;
};
Это похоже на хороший способ сделать это, так как я могу установить интервал самостоятельно, и работа с WMI всегда мне безопасна, так как это очень важно встроенное решение в Windows.
Другой способ сделать это было бы написать сценарий, что-то вроде:
$folderpath = 'C:\test'
$items = Get-ChildItem $folderpath
$currentdatetime = Get-Date
foreach($item in $items) {
If ($item.CreationTime > $currentdatetime.AddSeconds(-5)){
# Do some action
}
}
, который затем может быть запущен в системе в качестве запланированной задачи.
Мой вопрос - что это лучший способ сделать это? Из двух вариантов, которые я показал, является ли один из них более эффективным с точки зрения системных ресурсов или потенциальных ошибок?
Есть ли другие способы сделать это, что я не рассматривал?
Jisaak добавил ответ, который использует System.IO.FilesystemWatcher
. К сожалению, это не идеально для моих целей, так как это работает только тогда, когда оболочка, которая его выполнила, открыта, тогда как я хотел бы получить более постоянное решение (обновил название вопроса, чтобы отразить это)
HI Jisaak благодарит за ваш ответ. Почему, по-вашему, использование «FileSystemWatcher» - лучшее решение? Для этого также потребуется настроить запланированную задачу, не означает ли это, что есть больше обслуживания? Каковы преимущества этого, и что не так с длинным опросом папки? Конечно, я мог бы просто включить в свой скрипт действия мою постоянную регистрацию событий, чтобы отправить электронное письмо или уведомить меня каким-либо образом, не требуя «FileSystemWatcher». Еще раз спасибо за помощь! – Bassie
Ну, я ничего не изучал по производительности, но я думаю, что это самый эффективный способ отслеживания изменений в каталоге. Длительный опрос - это всегда самое худшее, что вы можете сделать. –
Спасибо jisaak. Я должен был упомянуть, что я уже использовал аналогичный метод, когда я регистрирую событие в оболочке. К сожалению, это не идеально, поскольку он длится только тогда, когда оболочка, выполняющая скрипт, остается открытой. В решениях, которые я разместил выше, зарегистрирован постоянный фильтр событий (который будет продолжать работать, даже если компьютер перезагружен), поэтому я рассматриваю эти методы. Я обновил свой вопрос, чтобы отразить это требование. – Bassie