Windows management instrumentation(WMI) provides
us with a way to access management information of the computers. WMI is of great use to the system administrators who want to automate administrative tasks
by writing scripts or applications. Programming in WMI can be done in power
shell, c++ applications or .net apps. Detailed info is available here :
http://msdn.microsoft.com/enus/library/windows/desktop/aa393964(v=vs.85).aspx
By management information we mean, WMI can retreive information like services on
the computer, logical disk information, information specific to a computer and
so on. In this article, we are going to write a windows forms application that
helps us to retrieve a list of services on a remote computer and operate on
them(start/stop).
Open Visual Studio 2008 and create a new windows forms application project. We
need to add a reference to System.Management to work with WMI.
Also, we are going to use impersonation to get access to a remote computer. Add
the following references
using
System.Management;
using
System.Security.Principal;
We are going to access a remote computer and for that we would need credentials to impersonate. So here is the form design that takes the remote
server name and the credentials as input
The WMI fetches data in the form of a query. These queries are very similar to
what we write to fetch data from a SQL database. Once we have provided the
server name and credentials we will fetch the services on that remote computer
on the Get Services button click.
private
void btnGetServices_Click(object
sender, EventArgs e)
{
ConnectionOptions conn =
new
ConnectionOptions();
conn.Impersonation = ImpersonationLevel.Impersonate;
conn.Username = txtUsername.Text;
conn.Password = txtPassword.Text;
ManagementScope
theScope = new
ManagementScope("\\\\"+txtServerName.Text+"\\root\\cimv2",
conn);
ManagementObjectSearcher
servSearcher = new
ManagementObjectSearcher(theScope, new
ObjectQuery("SELECT
* FROM Win32_Service"));
foreach (ManagementObject
servObj in servSearcher.Get())
{
lstServices.Items.Add(servObj["Caption"]);
}
}
The ManagementObjectSearcher lets us specify the query from where we need to
fetch the management data. Here, as we are working with windows services, we
would be fetching data from Win32_Service. (SELECT * FROM Win32_Service)
ManagementObjectSearcher.Get()method returns us a collection of management
objects. We iterate through the collection and add the service names to the
listbox on the form . servObj["Caption"] : why "caption" ? this you will find
out at the end of the article.
So now we are done with fetching the services that are running on a remote
server.
Now, we will select a service from the listbox and display its state
(Started/Stopped) in a label. We will pass the string of the selected index to
the "fetchServiceObject" method which will return us the management object of
that particular service. With the help of that management object we can get the
status of the service.
Selected Index Change Method :
private
void lstServices_SelectedIndexChanged(object
sender, EventArgs e)
{
ManagementObjectCollection
serviceobjs = fetchServiceObject(lstServices.SelectedItem.ToString());
foreach (ManagementObject
service in serviceobjs)
{
if (service["started"].Equals(true))
{
lblServState.Text = "Started";
}
else
{
lblServState.Text = "Stopped";
}
}
}
public
ManagementObjectCollection
fetchServiceObject(string service)
{
ConnectionOptions conn =
new
ConnectionOptions();
conn.Impersonation = ImpersonationLevel.Impersonate;
conn.Username = txtUsername.Text;
conn.Password = txtPassword.Text;
ManagementScope
theScope = new
ManagementScope("\\\\" +
txtServerName.Text + "\\root\\cimv2", conn);
ManagementObjectSearcher
serviceSearcher = new
ManagementObjectSearcher(theScope,
new ObjectQuery("SELECT
* FROM Win32_Service where Caption='" + service +
"'"));
return serviceSearcher.Get(); // Returns the
service where caption == listbox selected item
}
As already discussed, the Get() method will return the collection of
management objects so the return type of the method is
ManagementObjectCollection.
We can also start and stop the service. Below is the code
Stop a service :
private
void button1_Click(object
sender, EventArgs e)
{
ManagementObjectCollection
serviceObjs = fetchServiceObject(lstServices.SelectedItem.ToString());
foreach (ManagementObject
service in serviceObjs)
{
if (service["Started"].Equals(true))
{
service.InvokeMethod("StopService",
null);
}
}
}
Verify on the remote server and the service must have been stopped. This can be
restared from the below code.
Start a service :
private
void btnStartservice_Click(object
sender, EventArgs e)
{
ManagementObjectCollection
serviceObjs = fetchServiceObject(lstServices.SelectedItem.ToString());
foreach (ManagementObject
service in serviceObjs)
{
if (service["Started"].Equals(false))
{
service.InvokeMethod("StartService",
null);
}
}
}
We had used the ["Caption"] property to display the name of the service. Where
did this come from? Here is the list of all the Win32 classes and the
properties in each class.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394084%28v=vs.85%29.aspx
Similarly we can use the Win32_LogicalDisk to get the information related to the
disks such as the names,total space, free space etc. This code works for the
remote computers on the same domain. Sometimes you might face access issues
because of the firewall. Details of the troubleshooting can be found here
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394603(v=vs.85).aspx
Cheers !