C# WMI在C中查询无效,但在wbemtest实用程序中工作

C# WMI在C中查询无效,但在wbemtest实用程序中工作,c#,.net,wmi,wmi-query,C#,.net,Wmi,Wmi Query,我正在尝试创建一个WQLEventQuery,以便在C小程序中运行,该程序在指定文件夹中创建新文件夹时触发。我以前使用过WMI,我很熟悉它的工作原理。在将新文件添加到特定文件夹时,我成功创建了相同类型的eventquery。奇怪的是,我在调试中运行小程序时遇到了一个异常,但是如果我从windows中内置的“wbemtest”实用程序中执行相同的查询,那么在删除INTERVICE子句时不会抛出任何“invalid query”。但是,如果我没有在C代码中对WQLEventQuery对象设置With

我正在尝试创建一个WQLEventQuery,以便在C小程序中运行,该程序在指定文件夹中创建新文件夹时触发。我以前使用过WMI,我很熟悉它的工作原理。在将新文件添加到特定文件夹时,我成功创建了相同类型的eventquery。奇怪的是,我在调试中运行小程序时遇到了一个异常,但是如果我从windows中内置的“wbemtest”实用程序中执行相同的查询,那么在删除INTERVICE子句时不会抛出任何“invalid query”。但是,如果我没有在C代码中对WQLEventQuery对象设置WithinInterval属性,则会引发与所需轮询间隔相关的另一个异常。以下是上下文的一些代码片段:

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 = $@"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);
        }
    }
}
因此,查询字符串本质上是 从1中的uu InstanceCreationEvent中选择*其中TargetInstance为“Win32_子目录”,TargetInstance.GroupComponent='Win32_目录。Name=C:\\MonitoredDocs'


如果获取该查询字符串并删除INTERNAIN子句,wbemtest将其作为有效的WMI查询接受。当INTERNAIN子句存在时,它表示这是一个无效的查询。我使用的是来自的答案。如果您能帮助我找出如何使用此WQL事件查询,我将不胜感激。

因此,我更专注地阅读了我在上面发布的文章,并找到了一个实际可行的替代查询。查询字符串如下所示:

从1中的uu InstanceCreationEvent中选择*其中TargetInstance为'Win32_Directory',TargetInstance.Drive为'C',TargetInstance.Path为'\\Path\\to\\monitored\\Directory\'

*一个可能令人困惑的细节是路径值必须包含尾随字符\\

就代码而言,我修改过的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)
            };
        } 
    }
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)
            };
        } 
    }