Page 1 of 1

WMI Win32_ Classes and Properties Everything you always wanted to know but didn't know how to ask.

#1 StCroixSkipper  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 10
  • View blog
  • Posts: 121
  • Joined: 23-December 08

Posted 02 March 2010 - 05:42 PM

WMI provides a lot of information but sometimes it is hard to be able to browse the available content, the Win32_ classes and their properties. I've written a little application that allows me to browse the classes and their properties.

I think you'll be surprised to see the kinds of objects and the properties available. I've used this on my local machine but you can use WMI to see the classes and object available on remote machines too. You'll have to have the appropriate rights to see remote machine info but it is possible.

I've also got code to watch for WMI USB events so I can be notified when a USB device is added or removed from your system. If anyone is interested, I'll add it to this tutorial.

First, click on Visual Studio’s ‘File>New>Project’ menu and select ‘WPF Application’. Name your new project ‘WMIExplorerProject’.

The next thing I like to do is to rename all the parts and pieces from the ‘Window1’ default so I have more meaningful names. Right click on ‘Window1.xaml’ and rename it to ‘WMIExplorerMainWindow’. Then open the ‘App.xaml’ file and change the ‘StartupUri=”Window1.xaml”’ to ‘StartupUri=”WMIExplorerMainwindow.xaml”’. Then open the WMIExplorerMainwindow.xaml file and change ‘Window1’ to ‘WMIExplorerMainWindow’ for all occurrences.
Everything should now compile and build.

Since I'm learning WPF all my applications are WPF applications. Here is the App.xaml. It should be self explanatory.

<Application x:Class="WMIExplorerProject.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="WMIExplorerMainwindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>



For the UI I'm using a Grid with two columns and one row. Column 0 will contain a TreeView of all the Win32_ classes and their objects. When you click on an object, it will display the property data in the ListView in Column 0.

Since the length of the object names may be large, I've added a GridSplitter in Column 0 so you can resise the column to see more of the object name/description.

Here is the WMLExplorerMainwindow.xaml code:
<Window x:Class="WMIExplorerProject.WMIExplorerMainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Windows Management Instrumentation Explorer" 
        Height="1000" 
        Loaded="WMIExplorerMainWindow_Loaded">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300" MinWidth="300"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
        <TreeView Name="tvWmiClasses" 
                  Grid.Column="0" Grid.Row="0"
                  Margin="2,2,12,2"/>
        <ListView Name="lvWmiProperties"
                  Grid.Column="1"
                  Grid.Row="0"
                  Margin="2,2,12,2"/>
        <GridSplitter Width="5" Grid.Column="0" Grid.Row="0"/>
    </Grid>
</Window>



Now for the code. I'll try to explain some of the issues in comments in the code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// to use WMI you'll need to add this using statement and add a reference to the
// System.Management assembly.
using System.Management; 
 
namespace WMIExplorerProject
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class WMIExplorerMainWindow : Window
    {
        private bool _bFirstTimeRootItemSelected = true;

        // some classes have hundreds of Item.  Use this as a limit of the to display.
        private int _maxItems = 100; 

        public WMIExplorerMainWindow()
        {
            InitializeComponent();
        }

        //
        // This function simply calls InitializeWMIClassesTreeView() to initialize 
        // the tree view.
        //
        private void WMIExplorerMainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeWMIClassesTreeView();
        }

        private void InitializeWMIClassesTreeView()
        {
            //
            // add the root item to the TreeView
            //
            TreeViewItem tvRootItem = new TreeViewItem();
            tvRootItem.Header = "WMI Classes";
            tvRootItem.Selected += new RoutedEventHandler(TvRootPathItem_Selected);
            tvWmiClasses.Items.Add(tvRootItem);
        }

        void TvRootPathItem_Selected(object sender, RoutedEventArgs e)
        {
            // 
            // only search for subordinate classes the first time the root is selected.
            //
            if (_bFirstTimeRootItemSelected)
            {
                _bFirstTimeRootItemSelected = false;
                Cursor = Cursors.Wait;
                TreeViewItem tvRootItem = (TreeViewItem)sender;

                //
                // the "SELECT * FROM meta_class" query retrieves all of the
                // WMI Classes.
                //
                // I use the using statement because ManagementObjectSearcher
                // implements IDisposable.  I need it to clean up after I'm
                // through with it.
                //
                using (ManagementObjectSearcher moSearcher = new ManagementObjectSearcher("SELECT * FROM meta_class"))
                {
                    SortedList<string, ManagementObject> WmiClassList = new SortedList<string, ManagementObject>();
                    foreach (ManagementObject mo in moSearcher.Get())
                    {
                        //
                        // I wanted an alphabetized list of Win32 classes so
                        // I defined and filled a SortedList and I only wanted
                        // Win32_ classes.  But you could remove this test...
                        //
                        if (mo.ClassPath.ClassName.StartsWith("Win32_"))
                        {
                            WmiClassList.Add(mo.ClassPath.ClassName, mo);
                        }
                    }
                    foreach (KeyValuePair<string, ManagementObject> kvp in WmiClassList)
                    {
                        ManagementObject mo = kvp.Value;
                        TreeViewItem tvItem = new TreeViewItem();
                        tvItem.Header = mo.ClassPath.ClassName;
                        tvItem.ToolTip = mo.ClassPath.ToString();
                        tvItem.Selected += new RoutedEventHandler(TvPathItem_Selected);
                        tvRootItem.Items.Add(tvItem);
                    }
                }
                tvRootItem.IsExpanded = true;
                Cursor = Cursors.Arrow;
            }
        }

        void TvPathItem_Selected(object sender, RoutedEventArgs e)
        {
            Cursor = Cursors.Wait;
            TreeViewItem tvClassItem = (TreeViewItem)sender;
            if (tvClassItem.Items.Count <= 0)
            {
                string WmiClass = (string)tvClassItem.Header;
                // ActionCheck seems to hang so I special cased this class.
                if (!WmiClass.Contains("ActionCheck"))
                {
                    //
                    // the "SELECT * FROM ClassName" query returns all of
                    // the object of the class.
                    //
                    string sqlQuery = string.Format("SELECT * FROM {0}", tvClassItem.Header);
                    TreeViewItem tvItemToSelect = null;
                    lvWmiProperties.Items.Clear();

                    using (ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(sqlQuery))
                    {
                        foreach (ManagementObject mo in moSearcher.Get())
                        {
                            TreeViewItem tvItem = new TreeViewItem();
                            tvItemToSelect = tvItem;
                            string fullName =mo.ToString();

                            //
                            // if the full name contains Name=" then parse out the name and use it.
                            //
                            int idx = fullName.IndexOf("Name=\"");
                            if (idx != -1)
                            {
                                string name = fullName.Remove(0, idx + 6);
                                idx = name.IndexOf('"');
                                name = name.Substring(0, idx);
                                tvItem.Header = name;
                                tvItem.Selected += new RoutedEventHandler(TvWmiItem_Selected);
                            }
                            else 
                            {
                                //
                                // use the full name but don't add a 'Selected' event handler
                                // because I use this to construct the query and 
                                // I don't know how to contruct the query with
                                // the fullname.
                                //
                                tvItem.Header = fullName;
                            }
                            tvClassItem.Items.Add(tvItem);
                            //
                            // Some classes like Win32_Directory have thousands of 
                            // object so I've limited the TreeView to 100 objects of
                            // each class.
                            //
                            if (tvClassItem.Items.Count > _maxItems)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            Cursor = Cursors.Arrow;
        }

        void TvWmiItem_Selected(object sender, RoutedEventArgs e)
        {
            Cursor = Cursors.Wait;
            //
            // I need to clear the ListView before I add the properties of the newly
            // selected item.
            //
            lvWmiProperties.Items.Clear();
            TreeViewItem tvPathItem = (TreeViewItem)sender;
            TreeViewItem tvParentItem = (TreeViewItem)tvPathItem.Parent;
            string WmiClass = (string)tvParentItem.Header;
            StringBuilder WmiObject = new StringBuilder((string)tvPathItem.Header);
            WmiObject.Replace("\\", string.Empty);
            WmiObject.Replace(".", string.Empty);
            //
            // the query is constructed from the WMI Class and the object name.
            //
            string sqlQuery = string.Format("SELECT * FROM {0} WHERE Name = \"{1}\"", WmiClass, WmiObject);
            using (ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(sqlQuery))
            {
                foreach(ManagementObject mo in moSearcher.Get())
                {
                    PropertyDataCollection properties = mo.Properties;
                    // 
                    // add the properties of the ManagementObject to the ListView
                    //
                    foreach (PropertyData pd in properties)
                    {
                        if (pd.Name != null)
                        {
                            ListViewItem ivItem = new ListViewItem();
                            if (pd.Value != null)
                            {
                                ivItem.Content = string.Format("{0}:\t{1}", pd.Name, pd.Value.ToString());
                            }
                            else
                            {
                                ivItem.Content = string.Format("{0}:\tnull", pd.Name);
                            }
                            lvWmiProperties.Items.Add(ivItem);
                        }
                    }
                }
            }
            Cursor = Cursors.Arrow;
        }
    }
}



For the finishing touches. You need to remember that some of the classes and objects are protected by security. So when I'm working on a project that needs Admin rights I start Visual Studio by right clicking on it and clicking on 'Run as Administrator'.

Also, don't forget to add a reference to the System.Management assembly or you won't compile.

Is This A Good Question/Topic? 0
  • +

Replies To: WMI Win32_ Classes and Properties

#2 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1639
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Posted 05 March 2010 - 11:14 PM

I'm going to move this to WPF & Silverlight as well. Nice work though :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1