65.9K
CodeProject 正在变化。 阅读更多。
Home

管理远程计算机上的进程

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.57/5 (18投票s)

2007年3月8日

CPOL

1分钟阅读

viewsIcon

126946

downloadIcon

5680

本文介绍了如何使用 WMI 来管理远程计算机上的进程。

Screenshot - RemoteProcessController.png

引言

这篇文章提供了一个非常小的代码片段,帮助用户登录到远程机器,如果他们拥有管理员权限,则可以帮助管理进程。

我尽量使源代码尽可能简单,并在此处尝试解释它。

应用程序流程

应用程序流程非常简单

  1. 从域获取机器(使用Active Directory)
  2. 选择机器
  3. 提供用户名和密码(可以是域或机器特定的)
  4. 登录到远程机器
  5. 登录后,所有正在运行的进程及其一些详细信息将被加载到datagridview
  6. 选择任何进程以终止。您可以使用按钮或上下文菜单
  7. 如果想启动新进程,则输入进程名称并按“开始”

代码演练

变量声明:这是程序中用于管理流程、WMI 操作和 Active Directory 搜索的变量列表。

// List of domains that will be loaded in a combobox
private string []domains = {"india"};
// User name and password required to login to the selected machine
private string userName;
private string password;
private string machineName;
private string myDomain;
       
// I am using a datatable which contains 7 columns with these column names 
private string[] columnNames = { "Caption", "ComputerName", 
"Description", "Name", "Priority", "ProcessID", "SessionId" };        
// Hashtable to maintain list of machines and related users
private Hashtable hs = new Hashtable();
// Scope of the WMI operations
private ManagementScope myScope;
// Connection options to set user credentials
private ConnectionOptions connOptions;
// Retrieve list of management object based upon specific query
private ManagementObjectSearcher objSearcher;
// Handled management events
private ManagementOperationObserver opsObserver;
// Used to create new process on remote machine
private ManagementClass manageClass;
// Following are active directory objects to search users and computers
private DirectoryEntry entry;
private DirectorySearcher searcher;
private DirectorySearcher userSearcher;
private DataTable dt;
private DataColumn []dc = new DataColumn[7];

重要函数

此方法用于获取域中所有可用的机器

private void btnGetMachines_Click(object sender, EventArgs e)
{
    Cursor.Current = Cursors.WaitCursor;
            
    int index = 0;
    // Create an entry for domain
    entry = new DirectoryEntry("LDAP://" + cmbDomainList.Text);
    // Create a user searcher by using filter
    userSearcher = new DirectorySearcher(entry);
    userSearcher.Filter = ("(objectclass=user)");
    SearchResultCollection src = userSearcher.FindAll();            
    
    // Get all computers
    searcher = new DirectorySearcher(entry);
    searcher.Filter = ("(objectclass=computer)");
            
    try
    {
        // Get the result collection
        SearchResultCollection results = searcher.FindAll();
        foreach (SearchResult sr in results)
        {
            DirectoryEntry de = sr.GetDirectoryEntry();
            // Remove preceding "CN=" character string
            cmdMachinesInDomain.Items.Add(de.Name.Remove(0,3));
            // Also get the users
            DirectoryEntry de1 = src[index++].GetDirectoryEntry();
            cmbUsers.Items.Add(de1.Properties["cn"].Value.ToString());
            if (!hs.ContainsKey(de.Name))
            {
                hs.Add(de.Name.Remove(0, 3), 
                de1.Properties["cn"].Value.ToString());
            }
        }
        cmdMachinesInDomain.SelectedIndex = 0;                
        cmbUsers.SelectedIndex = 0;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        this.Cursor = Cursors.Default;
    }
}

这是一个非常重要的函数,因为它实际上连接到远程机器并调用特定的 WMI 查询。

private void ConnectToRemoteMachine()
{            
    int width = dataGridView1.Width;
    int singleColWidth;          
    // Make width of all columns same
    singleColWidth = width / dt.Columns.Count;
    
    userName = txtUserName.Text.Trim();
    password = txtPassword.Text.Trim();
    if (cmdMachinesInDomain.SelectedItem != null)
    {
        machineName = cmdMachinesInDomain.SelectedItem.ToString();
    }
    else if (cmdMachinesInDomain.SelectedText != string.Empty)
    {
        machineName = cmdMachinesInDomain.SelectedText;
    }
    else
    {
        machineName = cmdMachinesInDomain.Text;
    }

    myDomain = cmbDomainList.Text;

    try
    {
        connOptions = new ConnectionOptions();
        connOptions.Impersonation = ImpersonationLevel.Impersonate;
        connOptions.EnablePrivileges = true;
        // Here we can connect to machine by using domain credentials or by using 
        // machine specific credentials
        if (machineName.ToUpper() == Environment.MachineName.ToUpper())
        {
            // Create the management scope with given credentials
            myScope = new ManagementScope(@"\ROOT\CIMV2", connOptions);
        }
        else
        {
            if (chkUseDomain.Checked)
            {
                connOptions.Username = myDomain + "\\" + userName;
            }
            else
            {
                connOptions.Username = machineName + "\\" + userName;
            }
            connOptions.Password = password;
            myScope = new ManagementScope(@"\\" + machineName + 
                @"\ROOT\CIMV2", connOptions);
        }

        myScope.Connect();
        // Query on win32 process
        objSearcher = new ManagementObjectSearcher
        ("SELECT * FROM Win32_Process");
        opsObserver = new ManagementOperationObserver();
        objSearcher.Scope = myScope;
        string[] sep = { "\n", "\t" };
        toolStripStatusLabel1.Text = string.Empty;
        toolStripStatusLabel1.Text = 
        "Authentication successful. Getting processes..";
        dt.Rows.Clear();
        // Get all processes from the machine                
        foreach (ManagementObject obj in objSearcher.Get())
        {
            string caption = obj.GetText(TextFormat.Mof);
            string[] split = caption.Split
            (sep, StringSplitOptions.RemoveEmptyEntries);
            DataRow dr = dt.NewRow();
            // Iterate through the splitter
            for (int i = 0; i < split.Length; i++)
            {
                if (split[i].Split('=').Length > 1)
                {
                    // Extract the right name of the process
                    string []procDetails = split[i].Split('=');
                    procDetails[1] = procDetails[1].Replace(@"""", "");
                    procDetails[1] = procDetails[1].Replace(';', ' ');
                    switch (procDetails[0].Trim().ToLower())
                    {
                        case "caption":
                            dr[dc[0]] = procDetails[1];
                            break;
                        case "csname":
                            dr[dc[1]] = procDetails[1];
                            break;
                        case "description":
                            dr[dc[2]] = procDetails[1];
                            break;
                        case "name":
                            dr[dc[3]] = procDetails[1];
                            break;
                        case "priority":
                            dr[dc[4]] = procDetails[1];
                            break;
                        case "processid":
                            dr[dc[5]] = procDetails[1];
                            break;
                        case "sessionid":
                            dr[dc[6]] = procDetails[1];
                            break;
                    }
                }
            }
            dt.Rows.Add(dr);
        }
        bindingSource1.DataSource = dt.DefaultView;
        foreach (DataColumn col in dt.Columns)
        {
            DataGridViewTextBoxColumn dvc = new DataGridViewTextBoxColumn();
            dvc.ToolTipText = col.ColumnName;
            dvc.Name = col.ColumnName;
            dvc.HeaderText = col.ColumnName;
            dvc.DataPropertyName = col.ColumnName;
            dvc.Width = singleColWidth;
            dataGridView1.Columns.Add(dvc);
        }
        grpStartNewProcess.Enabled = true;
        btnEndProcess.Enabled = true;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        this.Cursor = Cursors.Default;
    }
}

此代码片段在远程机器上启动新进程。

private void btnStartNew_Click(object sender, EventArgs e)
{
    object[] arrParams = {txtNewProcess.Text.Trim()};
    try
    {
        manageClass =
            new ManagementClass(myScope,
        new ManagementPath("Win32_Process"), new ObjectGetOptions());
        manageClass.InvokeMethod("Create", arrParams);
        btnConnect_Click(sender, e);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

结论

这样,我们可以有效地使用 WMI 来管理远程机器上的进程。

历史

  • 2007年3月8日:初始发布
© . All rights reserved.