WmiLight
A simple and light wmi framework that supports native AOT.
Install / Use
/learn @MartinKuschnik/WmiLightREADME
WmiLight

What is WmiLight?
A simple and lightweight WMI framework for querying WMI, calling WMI methods, and subscribing to WMI events. It's a subset of the System.Management.Instrumentation namespace.
In which case should you use WmiLight?
The System.Management framework has some limitations:
-
Memory leaks on .NET Framework: The .NET Framework version of System.Management leaks a small amount of memory on each remote operation. Use WmiLight if your application is a service or runs a long time and you're sending a lot of remote queries.
-
No Native AOT support: System.Management does not support Native AOT deployment. Use WmiLight if you want to build Native AOT applications that interact with WMI.
Installation
This project is being distributed as a NuGet package, so open your Package Manager Console window and execute the following command:
<a href="https://www.nuget.org/packages/WmiLight/" target="_blank"> <img title="NuGet" src="https://github.com/MartinKuschnik/WmiLight/blob/master/doc/pics/install_nuget_package.JPG" alt="NuGet"/> </a>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 (UPN format recommended):
var opt = new WmiConnectionOptions() { EnablePackageEncryption = true };
var cred = new NetworkCredential("USER@DOMAIN", "PASSWORD");
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 stuff
}
}
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 stuff
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. <br/>
To link WmiLight statically, add <PublishWmiLightStaticallyLinked>true</PublishWmiLightStaticallyLinked> to your project file.
<PropertyGroup>
<PublishAot>true</PublishAot>
<PublishWmiLightStaticallyLinked>true</PublishWmiLightStaticallyLinked>
</PropertyGroup>
Trimming issue with .NET Standard libraries (Native AOT only)
When building a Native AOT application that encapsulates your WMI code in a .NET Standard library, the trimmer may remove essential code from WmiLight. In this scenario, the trimmer cannot detect that WmiLight is actually used by the Native AOT application and may remove necessary code.
Note: This issue only affects Native AOT builds.
Solution: Add the following to your Native AOT application's project file to prevent excessive trimming:
<ItemGroup>
<TrimmerRootAssembly Include="WmiLight" />
</ItemGroup>
This marks WmiLight as a root assembly for the trimmer, ensuring that all necessary code is preserved during the Native AOT compilation.
Other benefits:
-
easy usage
-
support for Native AOT deployment
-
no distinction between local and remote queries
-
Debugger Preview

Related Skills
openhue
342.5kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
342.5kElevenLabs text-to-speech with mac-style say UX.
weather
342.5kGet current weather and forecasts via wttr.in or Open-Meteo
tweakcc
1.5kCustomize Claude Code's system prompts, create custom toolsets, input pattern highlighters, themes/thinking verbs/spinners, customize input box & user message styling, support AGENTS.md, unlock private/unreleased features, and much more. Supports both native/npm installs on all platforms.
