Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programmatically determine which WMI property is the primary key of a class?

Tags:

c#

wmi

I need to dynamically determine which property of a WMI class is the primary key in C#.

I can manually locate this information using CIM Studio or the WMI Delphi Code Creator but I need to find all property names of a class and flag which is / are the key / keys... and I already know how to find the property names of a class.

Manual identification of the key is covered in a related answer and I'm hoping the author (I'm looking at RRUZ) might be able to fill me in on how they locate the key (or anyone else who might know).

Many thanks.

like image 434
Bosco Avatar asked Feb 16 '23 05:02

Bosco


2 Answers

To get the key field of a WMI class, you must iterate over the qualifiers of the properties for the WMI class and then search for the qualifier called key and finally check if the value of that qualifier is true.

Try this sample

using System;
using System.Collections.Generic;
using System.Management;
using System.Text;

namespace GetWMI_Info
{
    class Program
    {

        static string GetKeyField(string WmiCLass)
        {
            string key = null; 
            ManagementClass manClass = new ManagementClass(WmiCLass);
            manClass.Options.UseAmendedQualifiers = true;
            foreach (PropertyData Property in manClass.Properties)
                foreach (QualifierData Qualifier in Property.Qualifiers)
                    if (Qualifier.Name.Equals("key") && ((System.Boolean)Qualifier.Value))                        
                        return Property.Name;
            return key;                                                    
        }

        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine(String.Format("The Key field of the WMI class {0} is {1}", "Win32_DiskPartition", GetKeyField("Win32_DiskPartition")));
                Console.WriteLine(String.Format("The Key field of the WMI class {0} is {1}", "Win32_Process", GetKeyField("Win32_Process")));
            }
            catch (Exception e)
            {
                Console.WriteLine(String.Format("Exception {0} Trace {1}", e.Message, e.StackTrace));
            }
            Console.WriteLine("Press Enter to exit");
            Console.Read();
        }
    }
}
like image 197
RRUZ Avatar answered Apr 26 '23 20:04

RRUZ


For those interested I've expanded on RRUZ's answer by:

  • allowing the query to be run against a remote machine, and
  • adding support for classes with multiple primary keys (as is the case with Win32_DeviceBus).

    static void Main(string[] args)
    {
        foreach (var key in GetPrimaryKeys(@"root\cimv2\win32_devicebus"))
        {
            Console.WriteLine(key);
        }
    }
    
    static List<string> GetPrimaryKeys(string classPath, string computer = ".")
    {
        var keys = new List<string>();
        var scope = new ManagementScope(string.Format(@"\\{0}\{1}", computer, System.IO.Path.GetDirectoryName(classPath)));
        var path = new ManagementPath(System.IO.Path.GetFileName(classPath));
        var options = new ObjectGetOptions(null, TimeSpan.MaxValue, true);
        using (var mc = new ManagementClass(scope, path, options))
        {
            foreach (var property in mc.Properties)
            {
                foreach (var qualifier in property.Qualifiers)
                {
                    if (qualifier.Name.Equals("key") && ((System.Boolean)qualifier.Value))
                    {
                        keys.Add(property.Name);
                        break;
                    }
                }
            }
        }
        return keys;
    }
    
like image 45
Bosco Avatar answered Apr 26 '23 19:04

Bosco