2017-01-11 6 views
0

指定されたフォルダ内に新しいフォルダが作成されるたびにトリガされるC#アプレットで実行するWQLEventQueryを作成しようとしています。以前はWMIを使用していましたが、どのように動作するかに精通しています。特定のフォルダに新しいファイルが追加されたときに、同じタイプのイベントクエリーを作成しました。奇妙な部分は、デバッグ時にアプレットを実行する際に例外が発生することですが、Windowsに組み込まれている 'wbemtest'ユーティリティから同じクエリを実行しても、無効なクエリはスローされませんWithin節を削除すると。ただし、C#コードでWQLEventQueryオブジェクトのWithinIntervalプロパティを設定しないと、ポーリング間隔に関連して別の例外がスローされます。WMI C#で無効なクエリがwbemtestユーティリティで動作する

FolderMonitor.cs

using System; 
using System.Configuration; 
using System.Management; 
using MyProject.core.interfaces; 

namespace MyProject.monitor.WmiEventMonitors 
{ 
    public class FolderMonitor : IWQLMonitor 
    { 
     private const string _eventClassName = "__InstanceCreationEvent"; 
     private const string _isaType = "Win32_SubDirectory"; 

     private readonly IEventListenerManager _eListenerManager; 
     private readonly IFileProcessService _fileProcessService; 

     public WqlEventQuery Query { get; } 
     public string Path { get; } 

     public FolderMonitor(string path, IEventListenerManager eListenerManager, IFileProcessService fileProcessService) 
     { 
      _eListenerManager = eListenerManager; 
      _fileProcessService = fileProcessService; 

      if (string.IsNullOrEmpty(path)) 
       path = GetConfiguredDirectory(); 

      Path = path; 

      var queryParamPath = path.Replace(@"\", @"\\"); 

      //Query = new WqlEventQuery(); 
      //Query.QueryString = [email protected]"Select * From {_eventClassName} Within 1 Where TargetInstance Isa '{_isaType}' And TargetInstance.GroupComponent = 'Win32_Directory.Name={queryParamPath}'"; 

      Query = new WqlEventQuery 
      { 
       EventClassName = _eventClassName, 
       Condition = $"TargetInstance isa '{_isaType}' And TargetInstance.GroupComponent = 'Win32_Directory.Name={queryParamPath}'" 
       WithinInterval = new TimeSpan(0,5,0) 
      }; 
     } 

     public void HandleEvent(object sender, EventArrivedEventArgs e) 
     { 
      // when a new subfolder is created: 
      // 1) Log it somewhere? 
      // 2) Create a new WMI listener for that subfolder to detect file creation 
      string newDirPath = null; 
      try 
      { 
       foreach (PropertyData pd in e.NewEvent.Properties) 
       { 
        if (pd.Name != "TargetInstance") continue; 

        ManagementBaseObject mbo; 
        if ((mbo = pd.Value as ManagementBaseObject) != null) 
        { 
         using (mbo) 
         { 
          var newSubDir = mbo.Properties["PartComponent"]; 
          var newDir = newSubDir.Value as ManagementBaseObject; 
          newDirPath = $"{newDir.Properties["Drive"].Value}{newDir.Properties["Path"].Value}"; 
        } 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
       Console.WriteLine(ex.StackTrace); 
       throw; 
      } 

      if (!string.IsNullOrEmpty(newDirPath)) 
      { 
       var newFileMonitorEvent = new FileMonitor(newDirPath, _fileProcessService); 
       _eListenerManager.Add(newFileMonitorEvent); 
      } 
     } 


     private static string GetConfiguredDirectory() 
     { 
      return ConfigurationManager.AppSettings["Directory"].Trim(); 
     } 

    } 
} 

マイイベント登録クラス

using System; 
using System.Management; 
using MyProject.monitor.WmiEventMonitors; 

namespace MyProject.monitor 
{ 
    public interface IFileMonitorEventRegistrar 
    { 
     ManagementEventWatcher RegisterEventListener(IWQLMonitor newMonitorCandidate); 
     bool UnregisterEventListener(ManagementEventWatcher listener); 
    } 

    public class FileMonitorEventRegistrar : IFileMonitorEventRegistrar 
    { 
     public ManagementEventWatcher RegisterEventListener(IWQLMonitor newMonitorCandidate) 
     { 
      var scope = WmiUtility.GetConnectionScope(); 
      ManagementEventWatcher watcher = null; 
      try 
      { 
       watcher = new ManagementEventWatcher(scope, newMonitorCandidate.Query); 
       watcher.EventArrived += new EventArrivedEventHandler(newMonitorCandidate.HandleEvent); 
       watcher.Start(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.Message); 
       Console.WriteLine(e.StackTrace); 
       throw; 
      } 
      return watcher; 
     } 

     public bool UnregisterEventListener(ManagementEventWatcher listener) 
     { 
      listener.Stop(); 
      listener.Dispose(); 

      return true; 
     } 
    } 
} 

私のWMIユーティリティクラス

using System; 
using System.Management; 

namespace MyProject.monitor 
{ 
    public static class WmiUtility 
    { 
     private static ManagementScope _connectionScope; 
     private static ConnectionOptions _connectionOptions; 


     public static ManagementScope GetConnectionScope() 
     { 
      EstablishConnection(null, null, null, Environment.MachineName); 
      return _connectionScope; 
     } 


     private static ConnectionOptions SetConnectionOptions() 
     { 
      return new ConnectionOptions 
      { 
       Impersonation = ImpersonationLevel.Impersonate, 
       Authentication = AuthenticationLevel.Default, 
       EnablePrivileges = true 
      }; 
     } 


     private static ManagementScope SetConnectionScope(string machineName, ConnectionOptions options) 
     { 
      ManagementScope connectScope = new ManagementScope(); 
      connectScope.Path = new ManagementPath(@"\\" + machineName + @"\root\CIMV2"); 
      connectScope.Options = options; 

      try 
      { 
       connectScope.Connect(); 
      } 
      catch (ManagementException e) 
      { 
       Console.WriteLine(e.Message); 
       Console.WriteLine(e.StackTrace); 
       throw; 
      } 
      return connectScope; 
     } 


     private static void EstablishConnection(string userName, string password, string domain, string machineName) 
     { 
      _connectionOptions = SetConnectionOptions(); 
      if (domain != null || userName != null) 
      { 
       _connectionOptions.Username = domain + "\\" + userName; 
       _connectionOptions.Password = password; 
      } 
      _connectionScope = SetConnectionScope(machineName, _connectionOptions); 
     } 
    } 
} 

私のEventQueryマネージャークラス

:ここでは、コンテキストのためのいくつかのコードスニペットは、
using System; 
using System.Collections.Generic; 
using System.Management; 
using MyProejct.monitor.WmiEventMonitors; 

namespace MyProject.monitor 
{ 
    public interface IEventListenerManager : IDisposable 
    { 
     IDictionary<string, ManagementEventWatcher> RegisteredEvents { get; } 
     bool Add(IWQLMonitor eListener); 
     bool Remove(string monitoredPath); 
    } 

    public class EventListenerManager : IEventListenerManager 
    { 
     private bool _disposed; 

     private readonly IFileMonitorEventRegistrar _eventRegistrar; 

     public IDictionary<string, ManagementEventWatcher> RegisteredEvents { get; } 


     public EventListenerManager(IFileMonitorEventRegistrar eventRegistrar) 
     { 
      _eventRegistrar = eventRegistrar; 
      RegisteredEvents = new Dictionary<string, ManagementEventWatcher>(); 
     } 


     public bool Add(IWQLMonitor eListener) 
     { 
      RegisteredEvents.Add(eListener.Path, _eventRegistrar.RegisterEventListener(eListener)); 
      return true; 
     } 

     public bool Remove(string monitoredPath) 
     { 
      if (RegisteredEvents.ContainsKey(monitoredPath)) 
      { 
       _eventRegistrar.UnregisterEventListener(RegisteredEvents[monitoredPath]); 
       return RegisteredEvents.Remove(monitoredPath); 
      } 
      return true; 
     } 

     protected virtual void Dispose(bool disposing) 
     { 
      if (!_disposed) 
      { 
       if (disposing) 
       { 
        foreach (var item in RegisteredEvents) 
        { 
         Remove(item.Key); 
        } 
       } 

       _disposed = true; 
      } 
     } 


     public void Dispose() 
     { 
      Dispose(true); 
     } 
    } 
} 

オーケストクラス

using System; 
using System.Configuration; 
using System.IO; 
using System.Linq; 
using MyProejct.monitor.WmiEventMonitors; 
using MyProject.core.interfaces; 

namespace MyProject.monitor 
{ 
    public interface IFileMonitorService : IDisposable 
    { 
     void Initialize(); 
    } 

    public class FileMonitorService : IFileMonitorService 
    { 
     private bool _disposed; 

     private readonly IEventListenerManager _eventListenerManager; 
     private readonly IFileMonitorEventRegistrar _eventRegistrar; 
     private readonly IFileProcessService _fileProcessService; 
     private string _parentDirectory; 

     public FileMonitorService(IFileMonitorEventRegistrar eventRegistrar, IFileProcessService fileProcessService) 
     { 
      _eventRegistrar = eventRegistrar; 
      _fileProcessService = fileProcessService; 
      _eventListenerManager = new EventListenerManager(_eventRegistrar); 
     } 


     public void Initialize() 
     { 
      if (string.IsNullOrEmpty(_parentDirectory)) 
       _parentDirectory = ConfigurationManager.AppSettings["SFTPDirectory"].Trim(); 

      if (!_eventListenerManager.RegisteredEvents.Any()) 
      { 
       GenerateFileEventListeners(); 
       GenerateParentFolderListener(); 
      } 
     } 

     public void GenerateFileEventListeners() 
     { 
      if (!Directory.Exists(_parentDirectory)) 
       return; 

      var foldersToMonitor = Directory.EnumerateDirectories(_parentDirectory); 

      foreach (var folderPath in foldersToMonitor) 
      { 
       // Create a listener 
       var fileMonitor = new FileMonitor(folderPath, _fileProcessService); 
       _eventListenerManager.Add(fileMonitor); 
      } 
     } 

     public void GenerateParentFolderListener() 
     { 
      var folderMonitor = new FolderMonitor(_parentDirectory, _eventListenerManager, _fileProcessService); 
      _eventListenerManager.Add(folderMonitor); 
     } 

     public virtual void Dispose(bool disposing) 
     { 
      if (!_disposed) 
      { 
       if (disposing) 
       { 
        _eventListenerManager.Dispose(); 
        _parentDirectory = null; 
       } 

       _disposed = true; 
      } 
     } 

     public void Dispose() 
     { 
      Dispose(true); 
     } 
    } 
} 

だから、クエリ文字列は、1 TargetInstanceののISA内__InstanceCreationEvent SELECT * FROM」本質的 は 'Win32_SubDirectory' とTargetInstance.GroupComponent = 'Win32_Directory.Name = C:\\ MonitoredDocs' "

クエリ文字列を取り出してwithin節を削除すると、wbemtestはそれを有効なWMIクエリとして受け入れます。 within句が存在する場合、それは無効なクエリであると言います。私はthis articleから回答を使用しています。このWQL Event Queryをどのように動作させるかを理解する助けがあれば、感謝します。

答えて

0

私は上記の記事を読んでより焦点を当てて、実際に動作する別のクエリを見つけました。クエリ文字列は次のようになります。

Select * From __InstanceCreationEvent 1以内TargetInstance Isa 'Win32_Directory'およびTargetInstance.Drive = 'C:' And TargetInstance.Path = '\\ path \\ to \\ monitored \\ directory混乱することができます\\」

*詳細の1つは、パス値は、コードの面で末尾 『\\』

を含める必要があることを、私の修正FolderMonitor.csクラスはこのようになっていることである:(変化*!*!*)

public class FolderMonitor : IWQLMonitor 
    { 
     private const string _eventClassName = "__InstanceCreationEvent"; 

     *!*!*private const string _isaType = "Win32_Directory";*!*!* 

     private readonly IEventListenerManager _eListenerManager; 
     private readonly IFileProcessService _fileProcessService; 

     public WqlEventQuery Query { get; } 
     public string Path { get; } 

     public FolderMonitor(string path, IEventListenerManager eListenerManager, IFileProcessService fileProcessService) 
     { 
      _eListenerManager = eListenerManager; 
      _fileProcessService = fileProcessService; 

      if (string.IsNullOrEmpty(path)) 
       path = GetConfiguredDirectory(); 

      Path = path; 

      *!*!*var drive = Path.Substring(0, 2);*!*!* 
      *!*!*var queryPath = Path.Substring(2) + @"\";*!*!* 

      var queryParamPath = queryPath.Replace(@"\", @"\\"); 

      Query = new WqlEventQuery 
      { 
       EventClassName = _eventClassName, 

       *!*!*Condition = $"TargetInstance Isa '{_isaType}' And TargetInstance.Drive = '{drive}' And TargetInstance.Path = '{queryParamPath}'",*!*!* 

       WithinInterval = new TimeSpan(0,0,1) 
      }; 
     } 
    } 
関連する問題