65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET - 深入系统编程 - 第 2 部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (15投票s)

2004年3月10日

CPOL

1分钟阅读

viewsIcon

122171

downloadIcon

909

使用 C# 配置设备(第 2 部分)。如何枚举设备。

引言

在第 1 部分中,我演示了如何枚举设备类。现在让我们看看如何枚举该类的设备。

设备枚举

首先,我们再次看一下设备管理器信息图。这很简单 - 设备管理器在我们展开设备类树时枚举设备。

设备枚举的思路并不难理解

  • 使用设备类名获取类 GUID(SetupDiClassGuidsFromNameA 函数)
  • 获取设备类的设备信息集(SetupDiGetClassDevsA 函数)
  • 为每个设备获取设备信息数据(SetupDiGetClassDevsA 函数,此函数的第二个参数是设备类中的顺序设备索引,因此以设备索引 = 0, 1 等循环调用此函数)。
  • 通过 SetupDiGetDeviceRegistryPropertyA 函数从注册表中获取设备名称。

下面是 C# 代码,它将为 PC 的选定设备类枚举设备。

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);
        }

        }
    }
}

此控制台应用程序的命令行 - DevInfo classname

classname - 设备类的名称。您可以使用上一篇文章中的应用程序来查找正确的设备类名称。运行应用程序后,您可以在 PC 上查看任何设备类的设备。

摘要

现在我们可以将第一篇文章和这篇文章的代码结合起来,添加有关设备的信息(例如,资源,如 IRQ、端口等),并将其放入 Windows Forms 应用程序中。但这将是第 3 部分的主题。

© . All rights reserved.