Skip to content

MartinKuschnik/WmiLight

Repository files navigation

WmiLight Build NuGet Status

What is WmiLight?

A simple and light wmi framework. It has only one function: sending WMI queries. It's a subset of the System.Management.Instrumentation namespace.

In which case should you use WmiLight?

The .Net framework implementation has one big problem. It leaks a little bit memory on each remote operation. Use this framework if your application is a service or runs a long time and you're sending a lot of remote queries.

Installation

This project is being distributed as a NuGet package, so open your Package Manager Console window and execute the following command:

NuGet

How to use?

Query all running processes for the local machine:

using (WmiConnection con = new WmiConnection())
{
    foreach (WmiObject process in con.CreateQuery("SELECT * FROM Win32_Process"))
    {
        Console.WriteLine(process["Name"]);
    }
}

Query all partitions for a remote machine with credentials:

var opt = new WmiConnectionOptions() { EnablePackageEncryption = true };
var cred = new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN");

using (WmiConnection con = new WmiConnection(@"\\MACHINENAME\root\cimv2", cred, opt))
{
    foreach (WmiObject partition in con.CreateQuery("SELECT * FROM Win32_DiskPartition"))
    {
        Console.WriteLine(partition["Name"]);
    }
}

Query all partitions for a remote machine with Integrated Windows Authentication:

var opt = new WmiConnectionOptions() { EnablePackageEncryption = true };

using (WmiConnection con = new WmiConnection(@"\\MACHINENAME\root\cimv2", opt))
{
    foreach (WmiObject partition in con.CreateQuery("SELECT * FROM Win32_DiskPartition"))
    {
        Console.WriteLine(partition["Name"]);
    }
}

Calling a static WMI method:

using (WmiConnection connection = new WmiConnection())
using (WmiMethod createMethod = connection.GetMethod("Win32_Process", "Create"))
using (WmiMethodParameters methodParams = createMethod.CreateInParameters())
{
    methodParams.SetPropertyValue("CommandLine", "cmd.exe");
  
    uint result = connection.ExecuteMethod<uint>(createMethod, methodParams, out WmiMethodParameters outParams);
  
    if (result != 0)
            throw new Exception($"Win32_Process::Create(...) failed with {result}");
  
    uint processId =  outParams.GetPropertyValue<uint>("ProcessId");

    // ...
}

And the following code shows how to call a non-static WMI method:

using (WmiConnection connection = new WmiConnection())
{
    foreach (WmiObject process in connection.CreateQuery("SELECT * FROM Win32_Process"))
    {
        if (process.GetPropertyValue<string>("Name") == "cmd.exe")
        {
            using (WmiMethod terminateMethod = process.GetMethod("Terminate"))
            using (WmiMethodParameters parameters = terminateMethod.CreateInParameters())
            {
                parameters.SetPropertyValue("Reason", 20);

                uint result = process.ExecuteMethod<uint>(terminateMethod, parameters, out WmiMethodParameters terminateOutParameters2);

                if (result != 0)
                    throw new Exception($"Win32_Process::Terminate(...) failed with {result}");
            }
        }
    }
}

Get a notification if a process has started:

var opt = new WmiConnectionOptions() { EnablePackageEncryption = true };

using (WmiConnection connection = new WmiConnection(@"\\MACHINENAME\root\cimv2", opt))
{
    using (WmiEventSubscription sub = connection.CreateEventSubscription(
            "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process'", 
            x => Console.WriteLine("Process '{0}' started", x.GetPropertyValue<WmiObject>("TargetInstance").GetPropertyValue<string>("Name"))))
    {
        // ToDo: wait or do some other suff
    }
}

Alternative way to get a notification if a process has started:

var opt = new WmiConnectionOptions() { EnablePackageEncryption = true };

using (WmiConnection connection = new WmiConnection(@"\\MACHINENAME\root\cimv2", opt))
{
    using (WmiEventWatcher eventWatcher = connection.CreateEventWatcher("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process'"))
    {
        eventWatcher.EventArrived += EventWatcher_EventArrived;

        eventWatcher.Start();

        // ToDo: wait or do some other suff

        eventWatcher.Stop();

        eventWatcher.EventArrived -= EventWatcher_EventArrived;
    }
}

Native AOT deployment

WmiLight supports Native AOT deployment since Version 5.0.0.

It's also possible to link WmiLight statically to have only one executable working without the WmiLight.dll.
To link WmiLight statically, add <PublishWmiLightStaticallyLinked>true</PublishWmiLightStaticallyLinked> to your project file.

<PropertyGroup>
    <PublishAot>true</PublishAot>
    <PublishWmiLightStaticallyLinked>true</PublishWmiLightStaticallyLinked>
</PropertyGroup>

Other benefits:

  • easy usage

  • support for Native AOT deployment

  • no distinction between local and remote queries

  • Debugger Preview

    Debugger_Preview