我需要监控一个文件夹并在每次创建文件时执行一些操作。我有2个解决方案 - 酮使用WMI,哪里可以使用该过滤器(无论是从.MOF
文件或哪些寄存器永久MWI事件绑定一个Powershell的脚本调用)来轮询该文件夹每一秒:永久监控特定文件夹中文件创建的最有效和最可靠的方法
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
的答案。不幸的是,这对于我的目的并不理想,因为这只适用于执行它的shell是开放的,而我想要一个更持久的解决方案(更新问题的标题以反映这一点)
HI Jisaak感谢您的回答。你为什么认为使用FileSystemWatcher是一个更好的解决方案?这也需要建立一个计划任务,所以这不意味着有更多的维护?这样做有什么好处,以及长轮询文件夹有什么问题?当然,我可以在我的行动脚本中加入我的永久活动注册,以发送电子邮件或以某种方式通知我自己,而无需使用FileSystemWatcher再次感谢您的帮助! – Bassie
那么,我没有研究任何性能,但我认为这是追踪目录变化的最有效方式。长时间轮询总是最糟糕的,你可以做。 –
谢谢jisaak。我应该提到我已经使用了一个类似的方法,在shell中注册一个事件。不幸的是,这并不理想,因为它只能在执行脚本的shell保持打开的情况下持续。我上面发布的解决方案都注册了一个永久事件过滤器(即使PC重新启动也会继续运行),这就是为什么我正在查看这些方法。我更新了我的问题以反映这一要求。 – Bassie