示例#1
0
 /// <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();
                }
            }
         
        }