} // end _DoInstall()


        // This can throw a Win32Exception, a ManagementException, or an
        // OperationCanceledException.
        private int _RunCommand( string command, bool instaKill, ICauPluginCallbackBase callback )
        {
            int exitCode = -1;
            int processId = 0;
            string username = null;
            SecureString password = null;
            if( null != m_cred )
            {
                username = m_cred.UserName;
                password = m_cred.Password;
            }

            object gate = new object();

            ConnectionOptions co = new ConnectionOptions( null,        // locale
                                                          username,
                                                          password,
                                                          null,        // authority
                                                          ImpersonationLevel.Impersonate,
                                                          AuthenticationLevel.PacketPrivacy,
                                                          true,        // enable privileges
                                                          null,        // context
                                                          TimeSpan.Zero );
            string path = String.Format( CultureInfo.InvariantCulture, @"\\{0}\root\cimv2", m_machine );
            ManagementScope scope = new ManagementScope( path, co );
            ObjectGetOptions objGetOptions = new ObjectGetOptions();

            scope.Connect();

            // We start the query before launching the process to prevent any possibility
            // of a timing or PID recycling problem.
            WqlEventQuery query = new WqlEventQuery( "Win32_ProcessStopTrace" );
            EventWatcherOptions watcherOptions = new EventWatcherOptions( null, TimeSpan.MaxValue, 1 );
            using( ManagementEventWatcher watcher = new ManagementEventWatcher( scope, query, watcherOptions ) )
            {
                watcher.EventArrived += (sender, arg) =>
                {
                    int stoppedProcId = (int) (uint) arg.NewEvent[ "ProcessID" ];
                    if( stoppedProcId == processId )
                    {
                        exitCode = (int) (uint) arg.NewEvent[ "ExitStatus" ];

                        if( null != callback )
                        {
                            callback.WriteVerbose( String.Format( CultureInfo.CurrentCulture,
                                                                  "Process ID {0} on {1} exited with code: {2}",
                                                                  processId,
                                                                  m_machine,
                                                                  exitCode ) );
                        }

                        lock( gate )
                        {
                            Monitor.PulseAll( gate );
                        }
                    }
                };

                watcher.Start();

                int timeout = Timeout.Infinite;
                ManagementPath mPath = new ManagementPath( "Win32_Process" );
                using( ManagementClass mc = new ManagementClass( scope, mPath, objGetOptions ) )
                using( ManagementBaseObject inParams = mc.GetMethodParameters( "Create" ) )
                {
                    inParams[ "CommandLine" ] = command;
                    using( ManagementBaseObject outParams = mc.InvokeMethod( "Create", inParams, null ) )
                    {
                        int err = (int) (uint) outParams[ "returnValue" ];
                        if( 0 != err )
                        {
                            throw new Win32Exception( err );
                        }
                        processId = (int) (uint) outParams[ "processId" ];
                        Debug.Assert( processId > 0 );
                    }
                }

                if( null != callback )
                {
                    callback.WriteVerbose( String.Format( CultureInfo.CurrentCulture,
                                                          "Process launched on {0} with ID: {1}",
                                                          m_machine,
                                                          processId ) );
                }

                // If instaKill is true, we are trying to test our ability to receive
                // Win32_ProcessStopTrace events, so kill the process immediately.
                if( instaKill )
                {
                    SelectQuery killQuery = new SelectQuery( "SELECT * FROM Win32_Process WHERE ProcessId = " + processId );
                    using( ManagementObjectSearcher searcher = new ManagementObjectSearcher( scope, killQuery ) )
                    {
                        foreach( ManagementObject obj in searcher.Get() )
                        {
                            obj.InvokeMethod( "Terminate", new object[] { (uint) c_TestWmiExitCode } );
                            obj.Dispose();
                        }
                    }

                    // If we don't receive the Win32_ProcessStopTrace event within 10
                    // seconds, we'll assume it's not coming. In that case, there's
                    // probably a firewall problem blocking WMI.
                    timeout = 10000;
                }

                // Wait until the process exits (or we get canceled).
                lock( gate )
                {
                    // If we get canceled, we stop waiting for the remote process to
                    // finish and just leave it running.
                    using( m_cancelToken.Register( () => { lock( gate ) { Monitor.PulseAll( gate ); } } ) )
                    {
                        if( !Monitor.Wait( gate, timeout ) )
                        {
                            Debug.Assert( instaKill, "This call should not time out unless we are in the instaKill scenario." );
                            throw new ClusterUpdateException( "The Fabrikam CAU plugin is able to create a process on cluster node \"{0}\" using WMI, but is not able to receive process lifetime events. Check the firewalls on both this computer and the target node and ensure that the appropriate WMI rules are enabled.",
                                                              "WmiTestReceiveEventFailed",
                                                              ErrorCategory.ResourceUnavailable );
                        }
                    }
                }

                watcher.Stop();
                m_cancelToken.ThrowIfCancellationRequested();
            }

            return exitCode;
        } // end _RunCommand()
Esempio n. 2
0
        } // end _DoInstall()

        // This can throw a Win32Exception, a ManagementException, or an
        // OperationCanceledException.
        private int _RunCommand(string command, bool instaKill, ICauPluginCallbackBase callback)
        {
            int          exitCode  = -1;
            int          processId = 0;
            string       username  = null;
            SecureString password  = null;

            if (null != m_cred)
            {
                username = m_cred.UserName;
                password = m_cred.Password;
            }

            object gate = new object();

            ConnectionOptions co = new ConnectionOptions(null,         // locale
                                                         username,
                                                         password,
                                                         null,         // authority
                                                         ImpersonationLevel.Impersonate,
                                                         AuthenticationLevel.PacketPrivacy,
                                                         true,         // enable privileges
                                                         null,         // context
                                                         TimeSpan.Zero);
            string           path          = String.Format(CultureInfo.InvariantCulture, @"\\{0}\root\cimv2", m_machine);
            ManagementScope  scope         = new ManagementScope(path, co);
            ObjectGetOptions objGetOptions = new ObjectGetOptions();

            scope.Connect();

            // We start the query before launching the process to prevent any possibility
            // of a timing or PID recycling problem.
            WqlEventQuery       query          = new WqlEventQuery("Win32_ProcessStopTrace");
            EventWatcherOptions watcherOptions = new EventWatcherOptions(null, TimeSpan.MaxValue, 1);

            using (ManagementEventWatcher watcher = new ManagementEventWatcher(scope, query, watcherOptions))
            {
                watcher.EventArrived += (sender, arg) =>
                {
                    int stoppedProcId = (int)(uint)arg.NewEvent["ProcessID"];
                    if (stoppedProcId == processId)
                    {
                        exitCode = (int)(uint)arg.NewEvent["ExitStatus"];

                        if (null != callback)
                        {
                            callback.WriteVerbose(String.Format(CultureInfo.CurrentCulture,
                                                                "Process ID {0} on {1} exited with code: {2}",
                                                                processId,
                                                                m_machine,
                                                                exitCode));
                        }

                        lock ( gate )
                        {
                            Monitor.PulseAll(gate);
                        }
                    }
                };

                watcher.Start();

                int            timeout = Timeout.Infinite;
                ManagementPath mPath   = new ManagementPath("Win32_Process");
                using (ManagementClass mc = new ManagementClass(scope, mPath, objGetOptions))
                    using (ManagementBaseObject inParams = mc.GetMethodParameters("Create"))
                    {
                        inParams["CommandLine"] = command;
                        using (ManagementBaseObject outParams = mc.InvokeMethod("Create", inParams, null))
                        {
                            int err = (int)(uint)outParams["returnValue"];
                            if (0 != err)
                            {
                                throw new Win32Exception(err);
                            }
                            processId = (int)(uint)outParams["processId"];
                            Debug.Assert(processId > 0);
                        }
                    }

                if (null != callback)
                {
                    callback.WriteVerbose(String.Format(CultureInfo.CurrentCulture,
                                                        "Process launched on {0} with ID: {1}",
                                                        m_machine,
                                                        processId));
                }

                // If instaKill is true, we are trying to test our ability to receive
                // Win32_ProcessStopTrace events, so kill the process immediately.
                if (instaKill)
                {
                    SelectQuery killQuery = new SelectQuery("SELECT * FROM Win32_Process WHERE ProcessId = " + processId);
                    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, killQuery))
                    {
                        foreach (ManagementObject obj in searcher.Get())
                        {
                            obj.InvokeMethod("Terminate", new object[] { (uint)c_TestWmiExitCode });
                            obj.Dispose();
                        }
                    }

                    // If we don't receive the Win32_ProcessStopTrace event within 10
                    // seconds, we'll assume it's not coming. In that case, there's
                    // probably a firewall problem blocking WMI.
                    timeout = 10000;
                }

                // Wait until the process exits (or we get canceled).
                lock ( gate )
                {
                    // If we get canceled, we stop waiting for the remote process to
                    // finish and just leave it running.
                    using (m_cancelToken.Register(() => { lock ( gate ) { Monitor.PulseAll(gate); } }))
                    {
                        if (!Monitor.Wait(gate, timeout))
                        {
                            Debug.Assert(instaKill, "This call should not time out unless we are in the instaKill scenario.");
                            throw new ClusterUpdateException("The Fabrikam CAU plugin is able to create a process on cluster node \"{0}\" using WMI, but is not able to receive process lifetime events. Check the firewalls on both this computer and the target node and ensure that the appropriate WMI rules are enabled.",
                                                             "WmiTestReceiveEventFailed",
                                                             ErrorCategory.ResourceUnavailable);
                        }
                    }
                }

                watcher.Stop();
                m_cancelToken.ThrowIfCancellationRequested();
            }

            return(exitCode);
        } // end _RunCommand()