DEV Community

loading...
Cover image for Fetch Service Status & Storage Info remotely in C# using WMI

Fetch Service Status & Storage Info remotely in C# using WMI

chaitanya.dev
I am a Software Developer currently working on .Net & .Net Core microservices.
Originally published at chaitanyasuvarna.wordpress.com ・3 min read

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;
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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());
}
Enter fullscreen mode Exit fullscreen mode

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());
}
Enter fullscreen mode Exit fullscreen mode

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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!

Discussion (0)