I was recently working on a pet project where I wanted to find the status of some services on multiple server instances and display this on a web page so that I have a single page to look at if I want to check the status if any of my application services have stopped on any of the sever instances. I also wanted to be able to Start or Stop these services from the same page. With this in place I no longer needed to log into any of the remote servers to check up on the services. And just as an add-on, I also wanted to be able to look at the storage information on these servers so that I can take action on any of the drives that are filling up quickly.
While looking around trying to figure out the easiest way to create such a Web App I came across Windows Management Instrumentation which is the infrastructure for management data and operations on Windows-based operating systems. Developers can use WMI to remotely monitor the hardware and software on remote computers. Remote connections for managed code are accomplished through the System.Management namespace.
Let’s have a look at how we can go about fetching Service and Storage info remotely using WMI with the System.Management namespace.
Setting up ConntectionOptions
The ConnectionOptions class from the System.Management
namespace specifies all settings required to make a WMI connection. You can create a ConnectionOptions
object and use it without setting up any of it’s properties to connect to the remote computer with default connection options. In this example I have setup some of the properties based on my connection requirements to the remote servers.
ConnectionOptions connection = new ConnectionOptions();
connection.Username = "User";
connection.Password = "AStrongPassword";
connection.Authority = "ntlmdomain:DOMAINNAME";
connection.EnablePrivileges = true;
connection.Authentication = AuthenticationLevel.Default;
connection.Impersonation = ImpersonationLevel.Impersonate;
Connecting to remote server using ManagementScope
The ManagementScope class represents a scope for management operations. You can initialize a new ManagementScope
with a specific path and then connect the scope object to a namespace on a remote computer using the ConnectionOptions
object.
ManagementScope scope = new ManagementScope(
$"\\\\{serverName}\\root\\CIMV2", connection);
scope.Connect();
Fetching management information using ManagementObjectSearcher and ObjectQuery
The ObjectQuery class is used to specify a query in the ManagementObjectSearcher
.
The ManagementObjectSearcher class is used to retrieve a collection of management objects based on a specified query. This class is one of the more commonly used entry points to retrieving management information. In this example I have created the ObjectQuery
to fetch LogicalDisk info and I am using ManagementObjectSearcher
to get each disk’s info.
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_LogicalDisk");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
foreach (ManagementObject managementObject in searcher.Get())
{
Console.WriteLine("Drive Name :" +
managementObject["Name"].ToString());
Console.WriteLine("Volume Size :" +
managementObject["Size"].ToString());
Console.WriteLine("Free Space :" +
managementObject["FreeSpace"].ToString());
}
Similarly we can also fetch Service information like below
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Service");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
foreach (ManagementObject managementObject in searcher.Get())
{
Console.WriteLine("Service Name :" +
managementObject["DisplayName"].ToString());
Console.WriteLine("Service State :" +
managementObject["State"].ToString());
}
Using InvokeMethod() on a ManagementObject
We can use the method InvokeMethod() on a ManagementObject
to perform operations on it asynchronously. In the below example, I have created the ObjectQuery
to fetch the ManagementObject
to represent a specific service who’s DisplayName
is stored in service_name. I am then calling InvokeMethod()
to invoke the StartService
method with no options which will start the service on the remote server asynchronously.
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Service where
DisplayName= '" + service_name + "'");
using (ManagementObjectSearcher searcher = new
ManagementObjectSearcher(scope, query))
{
foreach (ManagementObject myservice in searcher.Get())
{
myservice.InvokeMethod("StartService", null);
}
}
Thus we have seen how we can use System.Management
namespace and it’s classes to fetch management info from Windows machines and perform actions remotely. You can see the entire ASP .Net Core Web App that I have created on my Github profile here.
I hope you found this interesting. Thanks for reading!
Top comments (0)