5

每次创建文件时,我都需要监视文件夹并执行一些操作。我有 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
    }
}

然后可以作为计划任务在系统上运行。

我的问题是 - 这样做的最佳方法是什么?在我展示的 2 个选项中,其中一个在系统资源或潜在错误方面本质上更有效吗?

还有其他我没有考虑过的方法吗?


Jisaak 添加了一个使用System.IO.FilesystemWatcher. 不幸的是,这对我的目的来说并不理想,因为这仅在执行它的外壳打开时才有效,而我想要一个更永久的解决方案(更新了问题的标题以反映这一点)

4

2 回答 2

4

您不想长时间轮询文件夹以查找文件更改,而应该使用一种机制,在创建文件时您会收到通知。

因此,您可以使用该类并使用cmdletFileSystemWatcher注册到created 事件处理程序。Register-ObjectEvent

$folder = 'C:\test'
$filter = '*.*'
$fileSystemWatcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
 IncludeSubdirectories = $true # Set this according to your requirements.
 NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}

$onCreated = Register-ObjectEvent $fileSystemWatcher Created -SourceIdentifier FileCreated -Action {
 $path = $Event.SourceEventArgs.FullPath
  Write-Host "File $Path was created".

}

运行这个来取消注册:

Unregister-Event -SourceIdentifier FileCreated
于 2016-04-27T11:11:50.220 回答
1

根据此处的讨论,使用这些类型的事件时,似乎在可靠性或性能方面不应该有任何问题。

ActiveScript 使用者的影响是微不足道的。如果您不创建连续触发的事件,则该事件是无害的。如果设计正确,我已经使用 thises vevents 近二十年了。

WQL 事件过滤器不会轮询。它使用 SENS 事件来生成响应。至少从 W2K 开始,SENS 就已成为 Windows 的一部分。它基于内核。大量的 Windows 基于 SENS。

他们还提到,虽然 PowerShell 可以使用大约 100MB 来启动,但 WMI 事件监视却不能(VBSCript - 用于ActiveScriptEvent操作的首选脚本语言也不能)。

由于我似乎无法在其他任何地方找到任何有关此的信息(即在可靠性/性能方面),我将不得不这样做,因此将使用 WMI/WQL/MOF 实现我的文件夹监视器。

本文还提供了一些有用的信息,供任何寻求更多详细信息的人使用。它还建议运行它而不是一些连续的应用程序是更好地利用系统资源,但是它没有提到这是否包括使用计划任务。

于 2016-04-28T13:57:12.393 回答