How to retrieve basic and advanced hardware and software information (GPU, Hard Drive, Processor, OS, Printers) in Winforms with C#

How to retrieve basic and advanced hardware and software information (GPU, Hard Drive, Processor, OS, Printers) in Winforms with C#

Apart from needing the hardware and software information about your system, it is always a good exercise for beginners to know how to list the hardware components of the operative system as this help you to understand more about programming or just to perform an inventory of the machine's hardware.

In this article, you'll learn how to retrieve basic and advanced information of the system using C# in Winforms.

Important note

In some examples, you'll need to add the following reference in your project to retrieve information about the system:

using System.Management;

However, in some Visual Studio versions (specifically in 2010 and later) you'll need to add the reference (.DLL) in your project manually too. To do that follow these steps:

  1. Right Click on Project, Add References

  2. Select the Assemblies (framework) Tab and Search for System.Management and finally add the reference and click OK.

Add System.Management reference visual studio manually

We need to add the System.Management to create queries in WMI Classes. Read more about retrieving WMI Classes in .NET in msdn here.

By the other side, remember that all the implementations that uses the ManagementObjectSearcher class to obtain system information, whose properties values are integer values (0-100) and those values aren't related to the property name (i.e with the Video_Controller GPU class in the Architecture property that returns a value between 0 and 9) and you expect a very specific value (like x86 or x64), then is probably that you're passing by some information! Please read the documentation of the class in the Microsoft developer network website (providen in every part of the article respectively) to get a detailed description of every property.

For example, as said before the Architecture property returns an integer (which doesn't make sense for you as value), however this value specifies the index (not the value itself) of the following table:

Index Value
0 x86
1 MIPS
2 Alpha
3 PowerPC
5 ARM
6 ia64 (Itanium-based systems)
9 x64

So it's up to you how to render the information in your application according to the information providen in the msdn website.

Now that you know that, let's get started!

Graphic card (GPU)

To get information about the GPU, we need to create a system query to the Win32_VideoController class using the ManagementObjectSearcher class.

Start by adding the following reference to your class:

using System.Management;

If you still see an error while using the class in your code, please read the Important notes at the beginning of the article.

If you did everything right, then you'll be able to query the Win32_VideoController class. The The Win32_VideoController WMI class represents the capabilities and management capacity of the video controller on a computer system running Windows.

To access the WMI class, we need as said before, create a query. This query can be created using the ManagementObjectSearcher class (available in System.Management). It retrieves 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.

See the following implementation of the ManagementObjectSearcher querying the Win32_VideoController class to retrieve advanced information about the GPU:

ManagementObjectSearcher myVideoObject = new ManagementObjectSearcher("select * from Win32_VideoController");

foreach (ManagementObject obj in myVideoObject.Get())
{
    Console.WriteLine("Name  -  " + obj["Name"]);
    Console.WriteLine("Status  -  " + obj["Status"]);
    Console.WriteLine("Caption  -  " + obj["Caption"]);
    Console.WriteLine("DeviceID  -  " + obj["DeviceID"]);
    Console.WriteLine("AdapterRAM  -  " + obj["AdapterRAM"]);
    Console.WriteLine("AdapterDACType  -  " + obj["AdapterDACType"]);
    Console.WriteLine("Monochrome  -  " + obj["Monochrome"]);
    Console.WriteLine("InstalledDisplayDrivers  -  " + obj["InstalledDisplayDrivers"]);
    Console.WriteLine("DriverVersion  -  " + obj["DriverVersion"]);
    Console.WriteLine("VideoProcessor  -  " + obj["VideoProcessor"]);
    Console.WriteLine("VideoArchitecture  -  " + obj["VideoArchitecture"]);
    Console.WriteLine("VideoMemoryType  -  " + obj["VideoMemoryType"]);
}

The ManagementObject of the Win32_VideoController has more properties, you can read more about this class and all the available properties in the microsoft developer network docs here.

Note: remember, hardware that is not compatible with Windows Display Driver Model (WDDM) returns inaccurate property values for instances of this class or just an empty value.

The output should be something similar to:

/** 
Name  -  NVIDIA GeForce GTX 760
Status  -  OK
Caption  -  NVIDIA GeForce GTX 760
DeviceID  -  VideoController1
AdapterRAM  -  2147483648
AdapterDACType  -  Integrated RAMDAC
Monochrome  -  False
InstalledDisplayDrivers  -  nvd3dumx.dll,nvwgf2umx.dll,nvwgf2umx.dll,nvwgf2umx.dll,nvd3dum,nvwgf2um,nvwgf2um,nvwgf2um
DriverVersion  -  21.21.13.7306
VideoProcessor  -  GeForce GTX 760
VideoArchitecture  -  5
VideoMemoryType  -  2
**/

Besides if you want to conver the AdapterRAM value to a human readable values (MB, GB) instead of bytes, you can use the mentioned SizeSuffix method in the Hard drives zone:

// Convert the string obj["AdapterRAM"] into a Long value
Console.WriteLine("AdapterRAM  -  " + SizeSuffix((long)Convert.ToDouble(obj["AdapterRAM"])));
// Outputs : AdapterRAM  -  2,0 GB

Hard drives (and other type of drives)

To get the information about the installed drives on the Desktop, we are going to depend of the DriveInfo class included in the System.IO namespace. This class provides access to information on a drive, it models a drive and provides methods and properties to query for drive information. Use DriveInfo to determine what drives are available, and what type of drives they are. You need to add the following reference to your class in case they're not already referenced:

using System;
using System.IO;

You can use it to query to determine the capacity and available free space on the drive. See the following example:

DriveInfo[] allDrives = DriveInfo.GetDrives();

foreach (DriveInfo d in allDrives)
{
    Console.WriteLine("Drive {0}", d.Name);
    Console.WriteLine("  Drive type: {0}", d.DriveType);
    if (d.IsReady == true)
    {
        Console.WriteLine("  Volume label: {0}", d.VolumeLabel);
        Console.WriteLine("  File system: {0}", d.DriveFormat);
        Console.WriteLine("  Available space to current user:{0, 15} bytes", d.AvailableFreeSpace);

        Console.WriteLine("  Total available space:          {0, 15} bytes", d.TotalFreeSpace);

        Console.WriteLine("  Total size of drive:            {0, 15} bytes ", d.TotalSize);
        Console.WriteLine("  Root directory:            {0, 12}", d.RootDirectory);
    }
}

The allDrives variable will be an iterable array in which every item contain information about one available disk in the system (the disk can be Removable [USB,USB Hard disk], Fixed [Hard Drive] and CDRom drives). As not every shown disk contain information (in the case of the CDRom when there's no CD inside), you need to check if the drive is available checking with an if statement the drive.IsReady property. The previous code would produce the following output in the Output console:

/**
Output of the information about the drives available in the system

Drive C:\
  Drive type: Fixed
  Volume label: 
  File system: NTFS
  Available space to current user:  1835493908480 bytes
  Total available space:            1835493908480 bytes
  Total size of drive:              1999804297216 bytes 
  Root directory:                     C:\
Drive D:\
  Drive type: CDRom
Drive E:\
  Drive type: Fixed
  Volume label: 
  File system: NTFS
  Available space to current user:   164813348864 bytes
  Total available space:             164813348864 bytes
  Total size of drive:               500096991232 bytes 
  Root directory:                     E:\
Drive F:\
  Drive type: Fixed
  Volume label: Carlos
  File system: NTFS
  Available space to current user:    39133581312 bytes
  Total available space:              39133581312 bytes
  Total size of drive:               320059994112 bytes 
  Root directory:                     F:\
Drive G:\
  Drive type: Removable
  Volume label: UBUNTU 16_1
  File system: FAT32
  Available space to current user:    30001135616 bytes
  Total available space:              30001135616 bytes
  Total size of drive:                31600672768 bytes 
  Root directory:                     G:\
**/

As you can see, about the free space and capacity of the drives, the value will be returned in Bytes. You can use the following implementation (function) to retrieve the short output in a more understandable value (MB,GB,TB). The value will be automatically converted to the most reasonable value (if terabyte available, then the value will be shown in terabytes):

static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

static string SizeSuffix(Int64 value)
{
    if (value < 0) { return "-" + SizeSuffix(-value); }
    if (value == 0) { return "0.0 bytes"; }

    int mag = (int)Math.Log(value, 1024);
    decimal adjustedSize = (decimal)value / (1L << (mag * 10));

    return string.Format("{0:n1} {1}", adjustedSize, SizeSuffixes[mag]);
}

To convert the long value in bytes to a human readable value, just use the SizeSuffix function in the values that return numeric values:

Console.WriteLine("  Available space to current user:{0, 15}", SizeSuffix(d.AvailableFreeSpace));
Console.WriteLine("  Total available space:          {0, 15}", SizeSuffix(d.TotalFreeSpace));
Console.WriteLine("  Total size of drive:            {0, 15} ", SizeSuffix(d.TotalSize));

The generated output values now should be more readable in the way you do with Windows:

/**
Output of the information about the drives available in the system with readable values

Drive C:\
  Drive type: Fixed
  Volume label: 
  File system: NTFS
  Available space to current user:         1,7 TB
  Total available space:                   1,7 TB
  Total size of drive:                     1,8 TB
  Root directory:                     C:\
Drive D:\
  Drive type: CDRom
Drive E:\
  Drive type: Fixed
  Volume label: 
  File system: NTFS
  Available space to current user:       153,5 GB
  Total available space:                 153,5 GB
  Total size of drive:                   465,8 GB
  Root directory:                     E:\
Drive F:\
  Drive type: Fixed
  Volume label: Carlos
  File system: NTFS
  Available space to current user:        36,4 GB
  Total available space:                  36,4 GB
  Total size of drive:                   298,1 GB
  Root directory:                     F:\
Drive G:\
  Drive type: Removable
  Volume label: UBUNTU 16_1
  File system: FAT32
  Available space to current user:        27,9 GB
  Total available space:                  27,9 GB
  Total size of drive:                    29,4 GB
  Root directory:                     G:\
**/

Processor(s)

To get information about the CPU, we need to create a system query to the Win32_Processor class using the ManagementObjectSearcher class.

Start by adding the following reference to your class:

using System.Management;

If you still see an error while using the class in your code, please read the Important notes at the beginning of the article.

If you did everything right, then you'll be able to query the Win32_Processor class. The Win32_Processor WMI class represents a device that can interpret a sequence of instructions on a computer running on a Windows operating system.

To access the WMI class, we need as said before, create a query. This query can be created using the ManagementObjectSearcher class (available in System.Management).

See the following implementation of the ManagementObjectSearcher querying the Win32_Processor class to retrieve advanced information about the CPU:

ManagementObjectSearcher myProcessorObject = new ManagementObjectSearcher("select * from Win32_Processor");

foreach (ManagementObject obj in myProcessorObject.Get())
{
    Console.WriteLine("Name  -  " + obj["Name"]);
    Console.WriteLine("DeviceID  -  " + obj["DeviceID"]);
    Console.WriteLine("Manufacturer  -  " + obj["Manufacturer"]);
    Console.WriteLine("CurrentClockSpeed  -  " + obj["CurrentClockSpeed"]);
    Console.WriteLine("Caption  -  " + obj["Caption"]);
    Console.WriteLine("NumberOfCores  -  " + obj["NumberOfCores"]);
    Console.WriteLine("NumberOfEnabledCore  -  " + obj["NumberOfEnabledCore"]);
    Console.WriteLine("NumberOfLogicalProcessors  -  " + obj["NumberOfLogicalProcessors"]);
    Console.WriteLine("Architecture  -  " + obj["Architecture"]);
    Console.WriteLine("Family  -  " + obj["Family"]);
    Console.WriteLine("ProcessorType  -  " + obj["ProcessorType"]);
    Console.WriteLine("Characteristics  -  " + obj["Characteristics"]);
    Console.WriteLine("AddressWidth  -  " + obj["AddressWidth"]);
}

The ManagementObject of the Win32_Processor has more properties, you can read more about this class and all the available properties in the microsoft developer network docs here.

The output should be something similar to:

/**
Name  -  Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz
DeviceID  -  CPU0
Manufacturer  -  GenuineIntel
CurrentClockSpeed  -  3300
Caption  -  Intel64 Family 6 Model 60 Stepping 3
NumberOfCores  -  4
NumberOfEnabledCore  -  4
NumberOfLogicalProcessors  -  4
Architecture  -  9
Family  -  205
ProcessorType  -  3
Characteristics  -  4
AddressWidth  -  64
*/

Operative system

To get information about the Operative System, we need to create a system query to the Win32_OperatingSystem class using the ManagementObjectSearcher class.

Start by adding the following reference to your class:

using System.Management;

If you still see an error while using the class in your code, please read the Important notes at the beginning of the article.

If you did everything right, then you'll be able to query the Win32_OperatingSystem class. The Win32_OperatingSystem WMI class represents a Windows-based operating system installed on a computer.

To access the WMI class, we need as said before, create a query. This query can be created using the ManagementObjectSearcher class (available in System.Management).

See the following implementation of the ManagementObjectSearcher querying the Win32_OperatingSystem class to retrieve advanced information about the Operative System:

ManagementObjectSearcher myOperativeSystemObject = new ManagementObjectSearcher("select * from Win32_OperatingSystem");

foreach (ManagementObject obj in myOperativeSystemObject.Get())
{
    Console.WriteLine("Caption  -  " + obj["Caption"]);
    Console.WriteLine("WindowsDirectory  -  " + obj["WindowsDirectory"]);
    Console.WriteLine("ProductType  -  " + obj["ProductType"]);
    Console.WriteLine("SerialNumber  -  " + obj["SerialNumber"]);
    Console.WriteLine("SystemDirectory  -  " + obj["SystemDirectory"]);
    Console.WriteLine("CountryCode  -  " + obj["CountryCode"]);
    Console.WriteLine("CurrentTimeZone  -  " + obj["CurrentTimeZone"]);
    Console.WriteLine("EncryptionLevel  -  " + obj["EncryptionLevel"]);
    Console.WriteLine("OSType  -  " + obj["OSType"]);
    Console.WriteLine("Version  -  " + obj["Version"]);
}

The ManagementObject of the Win32_OperatingSystem has more properties, you can read more about this class and all the available properties in the microsoft developer network docs here.

The output should be something similar to:

/**
Caption  -  Microsoft Windows 10 Pro
WindowsDirectory  -  C:\Windows
ProductType  -  1
SerialNumber  -  00000-00000-00000-00000
SystemDirectory  -  C:\Windows\system32
CountryCode  -  49
CurrentTimeZone  -  60
EncryptionLevel  -  256
OSType  -  18
Version  -  10.0.10586
*/

Network interface

To get information about the network interface, you can use the NetworkInterface class available in the System.Net.NetworkInformation namespace. This class provides configuration and statistical information for a network interface.

Start by adding the following references into your class:

using System;
using System.Net.NetworkInformation;

And check the following simple implementation that list all the available network interfaces and some of the available properties of every object:

NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();

if (nics == null || nics.Length < 1)
{
    Console.WriteLine("  No network interfaces found.");
}else{
    foreach (NetworkInterface adapter in nics)
    {
        IPInterfaceProperties properties = adapter.GetIPProperties();
        Console.WriteLine();
        Console.WriteLine(adapter.Description);
        Console.WriteLine(String.Empty.PadLeft(adapter.Description.Length, '='));
        Console.WriteLine("  Interface type .......................... : {0}", adapter.NetworkInterfaceType);
        Console.WriteLine("  Physical Address ........................ : {0}", adapter.GetPhysicalAddress().ToString());
        Console.WriteLine("  Operational status ...................... : {0}", adapter.OperationalStatus);
    }
}

You can read more about the NetworkInterface class in msdn here. The previous code should generate a similar output:

/**
Realtek PCIe GBE Family Controller
==================================
  Interface type .......................... : Ethernet
  Physical Address ........................ : XXXXXXXXXXXX
  Operational status ...................... : Up

TAP-Windows Adapter V9
======================
  Interface type .......................... : Ethernet
  Physical Address ........................ : XXXXXXXXXXXX
  Operational status ...................... : Down

Bluetooth Device (Personal Area Network)
========================================
  Interface type .......................... : Ethernet
  Physical Address ........................ : XXXXXXXXXXXX
  Operational status ...................... : Down

Software Loopback Interface 1
=============================
  Interface type .......................... : Loopback
  Physical Address ........................ : 
  Operational status ...................... : Up

Teredo Tunneling Pseudo-Interface
=================================
  Interface type .......................... : Tunnel
  Physical Address ........................ : 00000000000000E0
  Operational status ...................... : Up

Microsoft ISATAP Adapter
========================
  Interface type .......................... : Tunnel
  Physical Address ........................ : 00000000000000E0
  Operational status ...................... : Down
*/

However, you can create a more ellaborated example using NetworkInterfaces and the IPGlobalProperties to check if the network interface supports IPv4 and IPv6. It list the available bluetooth networks too if available:

public static void ShowNetworkInterfaces()
{
    IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties();
    NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
    Console.WriteLine("Interface information for {0}.{1}     ",
            computerProperties.HostName, computerProperties.DomainName);
    if (nics == null || nics.Length < 1)
    {
        Console.WriteLine("  No network interfaces found.");
        return;
    }

    Console.WriteLine("  Number of interfaces .................... : {0}", nics.Length);

    foreach (NetworkInterface adapter in nics)
    {
        IPInterfaceProperties properties = adapter.GetIPProperties();
        Console.WriteLine();
        Console.WriteLine(adapter.Description);
        Console.WriteLine(String.Empty.PadLeft(adapter.Description.Length, '='));
        Console.WriteLine("  Interface type .......................... : {0}", adapter.NetworkInterfaceType);
        Console.WriteLine("  Physical Address ........................ : {0}",
                    adapter.GetPhysicalAddress().ToString());
        Console.WriteLine("  Operational status ...................... : {0}",
            adapter.OperationalStatus);
        string versions = "";

        // Create a display string for the supported IP versions.
        if (adapter.Supports(NetworkInterfaceComponent.IPv4))
        {
            versions = "IPv4";
        }
        if (adapter.Supports(NetworkInterfaceComponent.IPv6))
        {
            if (versions.Length > 0)
            {
                versions += " ";
            }
            versions += "IPv6";
        }
        Console.WriteLine("  IP version .............................. : {0}", versions);
        //ShowIPAddresses(properties);

        // The following information is not useful for loopback adapters.
        if (adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback)
        {
            continue;
        }
        Console.WriteLine("  DNS suffix .............................. : {0}",
            properties.DnsSuffix);

        string label;
        if (adapter.Supports(NetworkInterfaceComponent.IPv4))
        {
            IPv4InterfaceProperties ipv4 = properties.GetIPv4Properties();
            Console.WriteLine("  MTU...................................... : {0}", ipv4.Mtu);
            if (ipv4.UsesWins)
            {

                IPAddressCollection winsServers = properties.WinsServersAddresses;
                if (winsServers.Count > 0)
                {
                    label = "  WINS Servers ............................ :";
                    //ShowIPAddresses(label, winsServers);
                }
            }
        }

        Console.WriteLine("  DNS enabled ............................. : {0}",
            properties.IsDnsEnabled);
        Console.WriteLine("  Dynamically configured DNS .............. : {0}",
            properties.IsDynamicDnsEnabled);
        Console.WriteLine("  Receive Only ............................ : {0}",
            adapter.IsReceiveOnly);
        Console.WriteLine("  Multicast ............................... : {0}",
            adapter.SupportsMulticast);
    }
}

The execution of the ShowNetwork should generate an output similar to:

/**
Interface information for **MyComputerName**.     
  Number of interfaces .................... : 6

Realtek PCIe GBE Family Controller
==================================
  Interface type .......................... : Ethernet
  Physical Address ........................ : XXXXXXXXXXXX
  Operational status ...................... : Up
  IP version .............................. : IPv4 IPv6
  DNS suffix .............................. : fritz.box
  MTU...................................... : 1500
  DNS enabled ............................. : False
  Dynamically configured DNS .............. : True
  Receive Only ............................ : False
  Multicast ............................... : True

TAP-Windows Adapter V9
======================
  Interface type .......................... : Ethernet
  Physical Address ........................ : XXXXXXXXXXXX
  Operational status ...................... : Down
  IP version .............................. : IPv4 IPv6
  DNS suffix .............................. : 
  MTU...................................... : 1500
  DNS enabled ............................. : False
  Dynamically configured DNS .............. : True
  Receive Only ............................ : False
  Multicast ............................... : True

Bluetooth Device (Personal Area Network)
========================================
  Interface type .......................... : Ethernet
  Physical Address ........................ : XXXXXXXXXXXX
  Operational status ...................... : Down
  IP version .............................. : IPv4 IPv6
  DNS suffix .............................. : 
  MTU...................................... : 1500
  DNS enabled ............................. : False
  Dynamically configured DNS .............. : True
  Receive Only ............................ : False
  Multicast ............................... : True

Software Loopback Interface 1
=============================
  Interface type .......................... : Loopback
  Physical Address ........................ : 
  Operational status ...................... : Up
  IP version .............................. : IPv4 IPv6

Teredo Tunneling Pseudo-Interface
=================================
  Interface type .......................... : Tunnel
  Physical Address ........................ : 00000000000000E0
  Operational status ...................... : Up
  IP version .............................. : IPv6
  DNS suffix .............................. : 
  DNS enabled ............................. : False
  Dynamically configured DNS .............. : False
  Receive Only ............................ : False
  Multicast ............................... : False

Microsoft ISATAP Adapter
========================
  Interface type .......................... : Tunnel
  Physical Address ........................ : 00000000000000E0
  Operational status ...................... : Down
  IP version .............................. : IPv6
  DNS suffix .............................. : fritz.box
  DNS enabled ............................. : False
  Dynamically configured DNS .............. : True
  Receive Only ............................ : False
  Multicast ............................... : False
*/

Sound card (audio devices)

To get information about the audio devices , we need to create a system query to the Win32_SoundDevice class using the ManagementObjectSearcher class.

Start by adding the following reference to your class:

using System.Management;

If you still see an error while using the class in your code, please read the Important notes at the beginning of the article.

If you did everything right, then you'll be able to query the Win32_SoundDevice class. The Win32_SoundDevice WMI class represents the properties of a sound device on a computer system running Windows.

To access the WMI class, we need as said before, create a query. This query can be created using the ManagementObjectSearcher class (available in System.Management).

The following snippet will list all the audio devices (microphones, speakers, sound card etc) and their properties:

ManagementObjectSearcher myAudioObject = new ManagementObjectSearcher("select * from Win32_SoundDevice");

foreach (ManagementObject obj in myAudioObject.Get())
{
    Console.WriteLine("Name  -  " + obj["Name"]);
    Console.WriteLine("ProductName  -  " + obj["ProductName"]);
    Console.WriteLine("Availability  -  " + obj["Availability"]);
    Console.WriteLine("DeviceID  -  " + obj["DeviceID"]);
    Console.WriteLine("PowerManagementSupported  -  " + obj["PowerManagementSupported"]);
    Console.WriteLine("Status  -  " + obj["Status"]);
    Console.WriteLine("StatusInfo  -  " + obj["StatusInfo"]);
    Console.WriteLine(String.Empty.PadLeft(obj["ProductName"].ToString().Length, '='));
}

The ManagementObject of the Win32_SoundDevice has more properties, you can read more about this class and all the available properties in the microsoft developer network docs here.

The output of the previous snippet should be something similar to:

/**
Name  -  Logitech Mic (QuickCam S5500)
ProductName  -  Logitech Mic (QuickCam S5500)
Availability  -  
DeviceID  -  USB\VID_046D&PID_09A1&MI_02\8&1DEC173F&0&0002
PowerManagementSupported  -  False
Status  -  OK
StatusInfo  -  3
=============================
Name  -  NVIDIA High Definition Audio
ProductName  -  NVIDIA High Definition Audio
Availability  -  
DeviceID  -  HDAUDIO\FUNC_01&VEN_10DE&DEV_0040&SUBSYS_1043847A&REV_1001\5&2F2C87F6&0&0001
PowerManagementSupported  -  False
Status  -  OK
StatusInfo  -  3
============================
Name  -  High Definition Audio-Gerät
ProductName  -  High Definition Audio-Gerät
Availability  -  
DeviceID  -  HDAUDIO\FUNC_01&VEN_10EC&DEV_0892&SUBSYS_1462D816&REV_1003\4&C65B857&0&0001
PowerManagementSupported  -  False
Status  -  OK
StatusInfo  -  3
===========================
Name  -  Creative X-Fi Audio Processor (WDM)
ProductName  -  Creative X-Fi Audio Processor (WDM)
Availability  -  
DeviceID  -  PCI\VEN_1102&DEV_000B&SUBSYS_00431102&REV_04\4&2F87A1B6&0&00E4
PowerManagementSupported  -  False
Status  -  OK
StatusInfo  -  3
===================================
Name  -  NVIDIA Virtual Audio Device (Wave Extensible) (WDM)
ProductName  -  NVIDIA Virtual Audio Device (Wave Extensible) (WDM)
Availability  -  
DeviceID  -  ROOT\UNNAMED_DEVICE\0000
PowerManagementSupported  -  False
Status  -  OK
StatusInfo  -  3
===================================================
*/

Printers

To get information about the audio devices , we need to create a system query to the Win32_Printer class using the ManagementObjectSearcher class.

Start by adding the following reference to your class:

using System.Management;

If you still see an error while using the class in your code, please read the Important notes at the beginning of the article.

If you did everything right, then you'll be able to query the Win32_Printer class. The Win32_Printer WMI class represents a device connected to a computer running on a Microsoft Windows operating system that can produce a printed image or text on paper or other medium.

To access the WMI class, we need as said before, create a query. This query can be created using the ManagementObjectSearcher class (available in System.Management).

The following snippet list all the available printer in the system (even the Microsoft Print to PDF service):

ManagementObjectSearcher myPrinterObject = new ManagementObjectSearcher("select * from Win32_Printer");

foreach (ManagementObject obj in myPrinterObject.Get())
{
    Console.WriteLine("Name  -  " + obj["Name"]);
    Console.WriteLine("Network  -  " + obj["Network"]);
    Console.WriteLine("Availability  -  " + obj["Availability"]);
    Console.WriteLine("Is default printer  -  " + obj["Default"]);
    Console.WriteLine("DeviceID  -  " + obj["DeviceID"]);
    Console.WriteLine("Status  -  " + obj["Status"]);
    
    Console.WriteLine(String.Empty.PadLeft(obj["Name"].ToString().Length, '='));
}

The ManagementObject of the Win32_Printer  has more properties, you can read more about this class and all the available properties in the microsoft developer network docs here.

The output should look something like:

/**
Name  -  Microsoft XPS Document Writer
Network  -  False
Availability  -  
Is default printer  -  False
DeviceID  -  Microsoft XPS Document Writer
Status  -  Unknown
=============================
Name  -  Microsoft Print to PDF
Network  -  False
Availability  -  
Is default printer  -  False
DeviceID  -  Microsoft Print to PDF
Status  -  Unknown
======================
Name  -  Fax
Network  -  False
Availability  -  
Is default printer  -  False
DeviceID  -  Fax
Status  -  Unknown
===
Name  -  Enviar a OneNote 2013
Network  -  False
Availability  -  
Is default printer  -  False
DeviceID  -  Enviar a OneNote 2013
Status  -  Unknown
=====================
Name  -  Brother HL-3070CW series
Network  -  False
Availability  -  
Is default printer  -  True
DeviceID  -  Brother HL-3070CW series
Status  -  Unknown
========================
**/

Have fun !

Become a more social person