Click here to Skip to main content
15,867,765 members
Articles / Programming Languages / C#
Article

.NET - Diving into System Programming - Part 2

Rate me:
Please Sign up or sign in to vote.
4.88/5 (15 votes)
9 Mar 2004CPOL1 min read 116.6K   908   56   26
Device configuration using C# (Part 2) . How to enumerate devices.

Introduction

In Part 1, I have demonstrated how to enumerate device classes. Now let us see how to enumerate devices of the class.

Device enumeration

First of all, let us look again at the picture with Device Manager information. It is easy - Device Manager enumerate devices when we expand the tree for device class.

Image 1

The idea of device enumeration is not difficult for understanding:

  • Get class Guid using device class name (SetupDiClassGuidsFromNameA function)
  • Get device info set for device class (SetupDiGetClassDevsA function)
  • Get device info data for every device (SetupDiGetClassDevsA function, second parameters for this function is sequential device index in the device class, so call this function in circle with device index = 0, 1, etc.).
  • Get device name from Registry via SetupDiGetDeviceRegistryPropertyA function.

Below you see code in C# that will enumerate devices for selected device class for PC.

C#
using System;
using System.Text;
using System.Runtime.InteropServices;

namespace DevInfo
{

    class DeviceInfo
    {

        public const int DIGCF_PRESENT    = (0x00000002);
        public const int MAX_DEV_LEN = 1000;
        public const int SPDRP_FRIENDLYNAME = (0x0000000C);  
          // FriendlyName (R/W)
        public const int SPDRP_DEVICEDESC = (0x00000000);    
          // DeviceDesc (R/W)

        [StructLayout(LayoutKind.Sequential)]
            public class SP_DEVINFO_DATA
                {
                 public int cbSize;
                 public Guid  ClassGuid;
                 public int DevInst;    // DEVINST handle
                 public ulong Reserved;
                };

        [DllImport("setupapi.dll")]//
        public static extern Boolean
          SetupDiClassGuidsFromNameA(string ClassN, ref Guid guids, 
            UInt32 ClassNameSize, ref UInt32 ReqSize);

        [DllImport("setupapi.dll")]
        public static extern IntPtr                //result HDEVINFO
          SetupDiGetClassDevsA(ref Guid ClassGuid, UInt32 Enumerator,
            IntPtr     hwndParent,  UInt32 Flags);

        [DllImport("setupapi.dll")]
        public static extern Boolean
          SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, UInt32 MemberIndex,
            SP_DEVINFO_DATA     DeviceInfoData);

        [DllImport("setupapi.dll")]
        public static extern Boolean
          SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

        [DllImport("setupapi.dll")]
        public static extern Boolean
          SetupDiGetDeviceRegistryPropertyA(IntPtr DeviceInfoSet,
          SP_DEVINFO_DATA     DeviceInfoData, UInt32 Property,
          UInt32   PropertyRegDataType, StringBuilder  PropertyBuffer,
          UInt32 PropertyBufferSize, IntPtr RequiredSize);



        public static int EnumerateDevices(UInt32 DeviceIndex, 
                string ClassName,
                StringBuilder DeviceName)
        {
         UInt32 RequiredSize = 0;
         Guid guid=Guid.Empty;
         Guid[] guids=new Guid[1];
         IntPtr NewDeviceInfoSet;
         SP_DEVINFO_DATA DeviceInfoData= new SP_DEVINFO_DATA();


         bool res=SetupDiClassGuidsFromNameA(ClassName,
                    ref guids[0],RequiredSize,
                    ref RequiredSize);

         if(RequiredSize==0)
               {
                //incorrect class name:
                DeviceName=new StringBuilder("");
                return -2;
               }

         if(!res)
          {
           guids=new Guid[RequiredSize];
           res=SetupDiClassGuidsFromNameA(ClassName,ref guids[0],RequiredSize,
                ref RequiredSize);

           if(!res || RequiredSize==0)
               {
           //incorrect class name:
                DeviceName=new StringBuilder("");
                return -2;
               }
          }

         //get device info set for our device class
         NewDeviceInfoSet=SetupDiGetClassDevsA(ref guids[0],0,IntPtr.Zero,
                     DIGCF_PRESENT);
         if( NewDeviceInfoSet.ToInt32() == -1 )
         if(!res)
               {
          //device information is unavailable:
                DeviceName=new StringBuilder("");
                return -3;
               }

            DeviceInfoData.cbSize = 28;
            //is devices exist for class
            DeviceInfoData.DevInst=0;
            DeviceInfoData.ClassGuid=System.Guid.Empty;
            DeviceInfoData.Reserved=0;

            res=SetupDiEnumDeviceInfo(NewDeviceInfoSet,
                   DeviceIndex,DeviceInfoData);
            if(!res) {
         //no such device:
                SetupDiDestroyDeviceInfoList(NewDeviceInfoSet);
                DeviceName=new StringBuilder("");
                return -1;
            }



        DeviceName.Capacity=MAX_DEV_LEN;
        if(!SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet,
          DeviceInfoData,
        SPDRP_FRIENDLYNAME,0,DeviceName,MAX_DEV_LEN,IntPtr.Zero) )
        {
         res = SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet,
          DeviceInfoData,SPDRP_DEVICEDESC,0,DeviceName,MAX_DEV_LEN, 
            IntPtr.Zero);
         if(!res){
         //incorrect device name:
                SetupDiDestroyDeviceInfoList(NewDeviceInfoSet);
                DeviceName=new StringBuilder("");
                return -4;
            }
        }
         return 0;
        }

        [STAThread]
        static void Main(string[] args)
        {
         StringBuilder devices=new StringBuilder("");
         UInt32 Index=0;
         int result=0;

         if(args.Length != 1)
          {
            Console.WriteLine("command line format:");
            Console.WriteLine("DevInfo <CLASSNAME>");
            return;
          }

         while(true)
          {
            result=EnumerateDevices(Index, args[0], devices);
            Index++;
            if(result == -2)
                    {
                     Console.WriteLine("Incorrect name of Class = {0}",
                       args[0]);
                     break;
                    }
            if(result == -1)break;
            if(result == 0)Console.WriteLine("Device{0} is {1}", 
              Index, devices);
        }

        }
    }
}

The command line for this console application - DevInfo classname

classname - the name of device class. You can use application from previous article to find correct device class name. After running application you can see devices for any device class on your PC.

Image 2

Summary

Now we can join code from the first article and this article, add information about devices (for example, resources like IRQs, ports, etc) and put it in the Windows Forms application. But it is a subject for Part 3.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Ukraine Ukraine
I am C++ Builder developer.
I am interesting in WMI, Shell, some deep
COM interface. Beside these I am Brainbench
Win32 API Master.
Now I very like Microsoft .NET and C#. I made some firsts OPOS drivers for Ukrainian fiscal printers.

Comments and Discussions

 
GeneralI'm getting a negative return at line 108 Pin
The-Great-Kazoo14-Apr-11 6:37
professionalThe-Great-Kazoo14-Apr-11 6:37 
AnswerRe: I'm getting a negative return at line 108 Pin
Selwyn Leeke14-Oct-12 10:01
Selwyn Leeke14-Oct-12 10:01 
QuestionCommercial License Pin
Zemien23-Jun-08 20:37
Zemien23-Jun-08 20:37 
AnswerRe: Commercial License Pin
Vladimir Afanasyev30-Jan-09 1:45
Vladimir Afanasyev30-Jan-09 1:45 
QuestionList devices by connection Pin
Alex Bogatov6-Jun-07 23:23
Alex Bogatov6-Jun-07 23:23 
AnswerRe: List devices by connection Pin
Vladimir Afanasyev3-Oct-07 23:21
Vladimir Afanasyev3-Oct-07 23:21 
QuestionEnumeration in .NET 20 ???? Pin
mandrei130-Mar-07 23:17
mandrei130-Mar-07 23:17 
AnswerRe: Enumeration in .NET 20 ???? Pin
Vladimir Afanasyev3-Oct-07 23:26
Vladimir Afanasyev3-Oct-07 23:26 
GeneralAuthorization request Pin
Fabio Zanetta19-Jan-07 3:34
Fabio Zanetta19-Jan-07 3:34 
GeneralRe: Authorization request Pin
Vladimir Afanasyev23-Feb-07 3:51
Vladimir Afanasyev23-Feb-07 3:51 
QuestionVC# to VC++ Help Pin
chanbx5-Nov-06 14:50
chanbx5-Nov-06 14:50 
QuestionVC# to VC++ Pin
chanbx5-Nov-06 14:50
chanbx5-Nov-06 14:50 
QuestionVC# to VC++ Help Pin
chanbx5-Nov-06 14:49
chanbx5-Nov-06 14:49 
Questiondevice state Pin
gumigyuri7-Mar-06 9:51
gumigyuri7-Mar-06 9:51 
AnswerRe: device state Pin
Vladimir Afanasyev8-Mar-06 21:29
Vladimir Afanasyev8-Mar-06 21:29 
QuestionRe: device state Pin
gumigyuri9-Mar-06 8:09
gumigyuri9-Mar-06 8:09 
AnswerRe: device state Pin
Vladimir Afanasyev9-Mar-06 20:59
Vladimir Afanasyev9-Mar-06 20:59 
QuestionListing device driver files with WMI Pin
mohcin26-Jan-06 2:17
mohcin26-Jan-06 2:17 
AnswerRe: Listing device driver files with WMI Pin
Vladimir Afanasyev26-Jan-06 3:30
Vladimir Afanasyev26-Jan-06 3:30 
General'{' missing (possibly '}' too) Pin
hobyrne5-Dec-05 4:12
hobyrne5-Dec-05 4:12 
GeneralRe: '{' missing (possibly '}' too) Pin
Vladimir Afanasyev5-Dec-05 6:27
Vladimir Afanasyev5-Dec-05 6:27 
GeneralRe: '{' missing (possibly '}' too) Pin
Vladimir Afanasyev5-Dec-05 6:32
Vladimir Afanasyev5-Dec-05 6:32 
GeneralIssues with WIN32 calls Pin
RLyon9-May-04 23:43
RLyon9-May-04 23:43 
GeneralRe: Issues with WIN32 calls Pin
Vladimir Afanasyev10-May-04 22:29
Vladimir Afanasyev10-May-04 22:29 
QuestionWhat about WMI? Pin
zucchini11-Mar-04 4:26
zucchini11-Mar-04 4:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.