Introduction
This article is a very small code snippet that help users to log on to a remote machine and if they have admin rights, then helps to manage the processes.
I have tried to keep the source code as simple as possible and also try to explain it here.
Application Flow
The application flow is very simple:
- Get the machine from domain (using active directory)
- Select the machine
- Give user name and password (either domain or machine specific)
- Login to remote machine
- On log on, list of all running processes with some details are loaded into
datagridview
- Select any process to terminate. You can use either button or context menu
- If you want to start a new process, then type the name of the process and press Start
Code Walkthrough
Variable Declaration: This is the list of variables used in the program to manage the flow, WMI operations and active directory searching.
private string []domains = {"india"};
private string userName;
private string password;
private string machineName;
private string myDomain;
private string[] columnNames = { "Caption", "ComputerName",
"Description", "Name", "Priority", "ProcessID", "SessionId" };
private Hashtable hs = new Hashtable();
private ManagementScope myScope;
private ConnectionOptions connOptions;
private ManagementObjectSearcher objSearcher;
private ManagementOperationObserver opsObserver;
private ManagementClass manageClass;
private DirectoryEntry entry;
private DirectorySearcher searcher;
private DirectorySearcher userSearcher;
private DataTable dt;
private DataColumn []dc = new DataColumn[7];
Important Functions
This method is used to get all machines available on the domain:
private void btnGetMachines_Click(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
int index = 0;
entry = new DirectoryEntry("LDAP://" + cmbDomainList.Text);
userSearcher = new DirectorySearcher(entry);
userSearcher.Filter = ("(objectclass=user)");
SearchResultCollection src = userSearcher.FindAll();
searcher = new DirectorySearcher(entry);
searcher.Filter = ("(objectclass=computer)");
try
{
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult sr in results)
{
DirectoryEntry de = sr.GetDirectoryEntry();
cmdMachinesInDomain.Items.Add(de.Name.Remove(0,3));
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;
}
}
This is a very important function as it actually connects to a remote machine and calls a WMI specific query.
private void ConnectToRemoteMachine()
{
int width = dataGridView1.Width;
int singleColWidth;
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;
if (machineName.ToUpper() == Environment.MachineName.ToUpper())
{
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;
}
}
This code snippet starts a new process on the remote machine.
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());
}
}
Conclusion
This way, we can have WMI used efficiently to manage processes on remote machines.
History
- 8th March, 2007: Initial post