/// <summary> /// USB 插入和拔出监测函数。 /// 使用ManagementEventWacher来预定特定系统事件,通过WqlEventQuery设置查询对象和条件以及其他属性(比如查询的轮询间隔), /// 通过ManagementScope设置查询路径范围。 /// </summary> public void USBRemoveWacher() { ManagementEventWatcher wacher = null; WqlEventQuery query = null; ManagementScope scope = null; try { scope = new ManagementScope("root\\CIMV2"); //设置WMI路径 query = new WqlEventQuery(); //设置查询的事件类名,条件,查询间隔,也可一次在构造函数中初始化 query.EventClassName = "__InstanceDeletionEvent"; query.Condition = @"TargetInstance ISA 'Win32_USBControllerdevice'"; query.WithinInterval = new TimeSpan(1000); wacher = new ManagementEventWatcher(scope, query); wacher.EventArrived += new EventArrivedEventHandler(onUSBRemoved); wacher.Start(); } catch (Exception ex) { MessageBox.Show(ex.Message); } this.Closed += (s, e) => { wacher.Stop(); wacher.Dispose(); }; }
public Task WaitForAsync(string name, CancellationToken cancellationToken) { _logger.WriteLine("Attempting {0} wait.", IsEfficient ? "efficient" : "inefficient"); var taskSource = new TaskCompletionSource<object>(); var query = IsEfficient ? new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName = '" + name + "'") : new EventQuery("SELECT TargetInstance FROM __InstanceCreationEvent WITHIN 0.5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name LIKE '" + name + "'"); ManagementEventWatcher watcher = null; try { watcher = new ManagementEventWatcher(query); cancellationToken.Register(() => { _logger.WriteLine("Received Cancel while waiting for '{0}'.", name); watcher.Stop(); watcher.Dispose(); taskSource.TrySetCanceled(); }); watcher.EventArrived += (sender, e) => { _logger.WriteLine("Received process start event for '{0}'.", name); watcher.Stop(); watcher.Dispose(); taskSource.TrySetResult(null); }; try { watcher.Start(); } catch (ManagementException) { if (!IsEfficient) throw; watcher.Dispose(); IsEfficient = false; return WaitForAsync(name, cancellationToken); } } catch (Exception) { if (watcher != null) watcher.Dispose(); throw; } return taskSource.Task; }
/// <summary>Runs some command.</summary> /// <param name="command">The command to run.</param> /// <param name="wmiScope"> The ManagementScope object to connect to. (default=none).</param> /// <param name="wait">Command's timeout expiration.</param> /// <remarks>IMPORTANT: 'domain/login/password' must have correct priviledges on the CIMV2 path ('Access denied' => see http://msdn.microsoft.com/en-us/library/windows/desktop/aa393613%28v=vs.85%29.aspx )</remarks> /// TODO: ?? Replace 'wait' parameter with some cancel callback ?? public static int Run(string command, ManagementScope wmiScope, double wait = double.PositiveInfinity) { // We let internal functions check and make defaults if (double.IsNaN(wait) || (wait < 0.0)) { throw new ArgumentException("wait range is 1-9999"); } // Process survey var processId = new[] { (uint)0 }; var exitCode = 0; var arguments = ((command ?? "")).Trim(); var watcher = (ManagementEventWatcher)null; var scope = (ManagementScope)null; // Note for the following code by mmcpherson 2014/02/13: // Originally I used the asynchronous implementation of WMI. Unfortunately using asynchronous would cause WMI access denied errors // if the source and target computers were not in the same domain!!! I could not find a simple solution for this. // // I had to modify the solution so that it is now semi-synchronous, which is a compromise. Using this method prevents the UI // thread from freezing, and still allows for some feedback whether a remote process has started or stopped. This is reliant // on that the WMI timeout period is set to wait for long enough of a time. try { // Connecting to WMI scope var span = TimeSpan.FromSeconds(0); // TODO: ?? relate to 'wait' or check cancel ?? // Removing use of wmi scope options for my own built in RemoteConnect //scope = connectToWmiScope(machine, domain, username, password, securePassword, span); scope = wmiScope; // Begin process stop watcher Func<uint> getProcessId = () => processId[0]; Action<int> setExitCode = (code) => exitCode = code; // Create the process processId[0] = createProcess(scope, arguments); // Create event query to be notified within 1 second of // a change in a service WqlEventQuery query = new WqlEventQuery("SELECT * From WIN32_ProcessStopTrace WHERE ProcessID=" + getProcessId()); // Initialize an event watcher and subscribe to events // that match this query watcher = new ManagementEventWatcher(scope, query); // times out watcher.WaitForNextEvent in 5 seconds watcher.Options.Timeout = new TimeSpan(0, 0, (int)wait); // Block until the next event occurs // Note: this can be done in a loop if waiting for // more than one occurrence ManagementBaseObject e = watcher.WaitForNextEvent(); //Cancel the subscription watcher.Stop(); return exitCode; /* * // TODO: THe following can be implemented for detecting timeouts & restarted servers to prevent issues with timeout exceptions * http://stackoverflow.com/questions/12159989/asynchronous-wmi-event-handling-in-net ManagementEventWatcher w = new ManagementEventWatcher(managementScope, new WqlEventQuery("select * from Win32_ProcessStopTrace where ProcessId=" + ProcessId)); w.Options.Timeout = new TimeSpan(0, 0, 0, 0, 1); DateTime start = DateTime.Now; while (Status == StatusNotStarted) //default status(just strings) { try { var ev = w.WaitForNextEvent(); ReturnCode = (uint)ev.Properties["ExitStatus"].Value; Status = (ReturnCode == 0) ? StatusOk : StatusFailed; } catch (ManagementException ex) { if (!ex.Message.Contains("Timed out")) throw ex; try { Ping p = new Ping(); PingReply reply = p.Send(MachineIP); if (reply.Status != IPStatus.Success) Status = StatusFailed; else { DateTime end = DateTime.Now; TimeSpan duration = end - start; if (duration.TotalMilliseconds > Timeout) { Status = StatusFailed; } } } */ } catch (Exception ex) { var msg = dumpRunArguments(command, wait); msg = string.Format("Command execution failed:\n{0}", msg); if (Log.WriteLog != null) { Log.WriteLog("ERROR: " + msg); } if (ex is TimeoutException) { if (Log.WriteLog != null) { Log.WriteLog("ERROR: Exception is timeout, trying to kill process: "+ ex.Message); } if ((scope != null) && (processId[0] != 0)) { bool found; tryKillProcess(scope, processId[0], out found); } } throw new Exception(msg, ex); } finally { if (watcher != null) { watcher.Stop(); watcher.Dispose(); } } }