5

フォルダーを監視し、ファイルが作成されるたびに何らかのアクションを実行する必要があります。私には2つの解決策があります.1つは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 つのオプションのうちの 1 つは、システム リソースまたはエラーの可能性に関して本質的により効率的ですか?

私が考慮していないこれを行う他の方法はありますか?


Jisaak は、 を使用する回答を追加しましたSystem.IO.FilesystemWatcher。残念ながら、これは私の目的には理想的ではありません.これは、それを実行したシェルが開いている間にのみ機能するためです.

4

2 に答える 2

4

ファイルの変更についてフォルダーを長時間ポーリングするのではなく、ファイルが作成されたときに通知を受け取るメカニズムを使用する必要があります。

したがって、FileSystemWatcherクラスを使用し、コマンドレットを使用して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 は、正しく設計されていればほぼ 20 年間問題なく使用してきました。

WQL イベント フィルタはポーリングしません。SENS イベントを使用して応答を生成します。SENS は、少なくとも W2K 以降、Windows の一部となっています。これはカーネルに基づいています。多くの Windows は SENS に基づいています。

彼らはまた、PowerShell は起動に約 100MB を使用できますが、WMI イベント監視はそうではありません (また、ActiveScriptEventアクションに推奨されるスクリプト言語である VBSCript もそうではありません)。

これに関する情報がどこにも見つからないように見えるので (つまり、信頼性/パフォーマンスの点で)、これを実行する必要があるため、WMI/WQL/MOF を使用してフォルダー モニターを実装します。

この記事には、詳細を知りたい人に役立つ情報も含まれています。また、継続的なアプリケーションの代わりにこれを実行すると、システム リソースがより有効に使用されることも示唆されていますが、これにスケジュールされたタスクの使用が含まれるかどうかについては言及されていません。

于 2016-04-28T13:57:12.393 に答える