程序读取计算机设备管理器中各设备的状态(启用/禁用)?(转自大富翁)

此部分代码请大家给加上注释。

const
  DEV_CLASS_NAME    = 'Net';
  DEM_CLASS_NAME    = 'MEDIA';
  DEC_CLASS_NAME    = 'CDROM';
  DEU_CLASS_NAME    = 'USB';
  DEP_CLASS_NAMW    = 'ports';
  UNKNOWN_DEVICE    = '<未知设备>';

private
    { Private declarations }
    DevState: Array of Boolean;
    procedure RefreshDevState;

    procedure EnumNetDevice;   //获得网卡 信息
    function IsClassHidden(const ClassGUID: PGUID): Boolean; //被EnumNetDevice调用
    function ConstructDeviceName(DeviceInfoSet: HDEVINFO;    //被EnumNetDevice调用
        DeviceInfoData: PSP_DEVINFO_DATA; Buffer: PAnsiChar; Length: ULONG): Boolean;
    function GetRegistryProperty(DeviceInfoSet: HDEVINFO;    //被EnumNetDevice调用
        DeviceInfoData: PSP_DEVINFO_DATA; AProperty: ULONG; Buffer: PAnsiChar;
        Length: ULONG): Boolean;
    function IsDevDisable(DevIndex: DWORD; hDevInfo: HDEVINFO): Boolean; //被EnumNetDevice调用
    function ChangeDevState(DevIndex, NewState: DWORD): BOOL;  //改变网卡状态
  public
    { Public declarations }
  end;

var
  DevForm: TDevForm;

implementation

{$R *.dfm}

procedure TDevForm.EnumNetDevice;  //获得网卡信息
var
    DeviceInfoSet: HDEVINFO;
    DeviceInfoData: SP_DEVINFO_DATA;
    i: Integer;
    Status, Problem: DWORD;
    ClassName: PChar;
    ClassSize, ReqClassSize: DWORD;
    DeviceName: PChar;
begin
    clbDevList.Clear;

    DeviceInfoSet:=SetupDiGetClassDevs(Nil,Nil,0,DIGCF_ALLCLASSES or DIGCF_PRESENT);
    if DeviceInfoSet = Pointer(INVALID_HANDLE_VALUE) then
      Exit;
    ClassSize:=255;
    GetMem(ClassName,256);
    try
      DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA); //枚举硬件,获得需要的接口

      i:=0;
      while SetupDiEnumDeviceInfo(DeviceInfoSet,i,@DeviceInfoData) do
      begin
          Inc(i);

          if not SetupDiClassNameFromGuid(@DeviceInfoData.ClassGuid,ClassName,ClassSize,
              @ReqClassSize) then
          begin
              if ReqClassSize>ClassSize then
              begin
                FreeMem(ClassName);
                ClassSize:=ReqClassSize;
                GetMem(ClassName,ClassSize+1);
                if not SetupDiClassNameFromGuid(@DeviceInfoData.ClassGuid,ClassName,ClassSize,
                    @ReqClassSize) then
                  Exit;
            end
            else
                Exit;
        end;

       if  not SameText(ClassName,DEV_CLASS_NAME) and  not SameText(ClassName,DEM_CLASS_NAME) and
           not SameText(ClassName,DEC_CLASS_NAME) and not SameText(ClassName,DEU_CLASS_NAME) and
           not SameText(ClassName,DEP_CLASS_NAMW) then
          Continue;

        if CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst,0)
            <> CR_SUCCESS then
          Exit;

        if ((Status and DN_NO_SHOW_IN_DM)<>0) or
            IsClassHidden(@DeviceInfoData.ClassGuid) then
          Continue;

        GetMem(DeviceName,256);  //给DeviceName变量分配 256 的内存
        ZeroMemory(DeviceName,256);   //给DeviceName的每个单元赋值  值为 零
        ConstructDeviceName(DeviceInfoSet,@DeviceInfoData,DeviceName,255); //获得了 DeviceName的值
        if IsDevDisable(i-1,DeviceInfoSet) then
          begin
              clbDevList.Items.AddObject(StrPas(DeviceName)+'-----'+classname,TObject(i-1));  //把DeviceName的值加入到列表中i-1行
              clbDevList.Checked[clbDevList.Count-1]:= IsDevDisable(i-1,DeviceInfoSet); // Checked的值为true
          end;
        FreeMem(DeviceName); //释放DeviceName所占的内存
      end;
    finally
      FreeMem(ClassName);
      SetupDiDestroyDeviceInfoList(DeviceInfoSet);
    end;
end;

function TDevForm.ConstructDeviceName(DeviceInfoSet: HDEVINFO;  //构造 DeviceName 的值
  DeviceInfoData: PSP_DEVINFO_DATA; Buffer: PAnsiChar;
  Length: ULONG): Boolean;
begin
    Result:=True;

    if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_FRIENDLYNAME,
        Buffer,Length) then
    begin
        if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_DEVICEDESC,
            Buffer,Length) then
        begin
            if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_CLASS,
                Buffer,Length) then
            begin
                if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_CLASSGUID,
                    Buffer,Length) then
                begin
                    StrCopy(Buffer,UNKNOWN_DEVICE);   //获得 DeviceName 的值 为‘未知设备’
                end
                else
                    Result:=False;
            end;
        end;
    end;
end;

function TDevForm.GetRegistryProperty(DeviceInfoSet: HDEVINFO;
  DeviceInfoData: PSP_DEVINFO_DATA; AProperty: ULONG; Buffer: PAnsiChar;
  Length: ULONG): Boolean;
var
    ReqLen: DWORD;
begin
    Result:=False;

    while not SetupDiGetDeviceRegistryProperty(DeviceInfoSet,DeviceInfoData,
       AProperty,Nil,Buffer,Length,@ReqLen) do
    begin
        if GetLastError() = ERROR_INVALID_DATA then
          break
        else
        if GetLastError() = ERROR_INSUFFICIENT_BUFFER then
        begin
            if Assigned(Buffer) then
              FreeMem(Buffer);
              Length:=ReqLen;
              GetMem(Buffer,Length+1);
        end
        else
            Exit;
    end;
    Result:=Buffer^<>#0;
end;

function TDevForm.IsClassHidden(const ClassGUID: PGUID): Boolean;
var
    hKeyClass: HKEY;
begin
    Result:=False;

    hKeyClass := SetupDiOpenClassRegKey(ClassGuid,KEY_READ);  //获得KEY值
    if hKeyClass<>0 then
    begin
        Result:= RegQueryValueEx(hKeyClass,REGSTR_VAL_NODISPLAYCLASS,Nil,Nil,NIl,Nil) = ERROR_SUCCESS; //查找KEY值,返回值为布尔型
        RegCloseKey(hKeyClass);
    end;
end;

function TDevForm.IsDevDisable(DevIndex: DWORD;
  hDevInfo: HDEVINFO): Boolean;
var
    DeviceInfoData: SP_DEVINFO_DATA;
    Status, Problem: DWORD;
begin
    Result:=False;
    DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);

    if not SetupDiEnumDeviceInfo(hDevInfo,DevIndex,@DeviceInfoData) then
      Exit;

    if CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS then
      Exit;

    Result:=((Status and DN_DISABLEABLE)<>0) and (CM_PROB_HARDWARE_DISABLED <> Problem);
end;

function TDevForm.ChangeDevState(DevIndex, NewState: DWORD): BOOL;  // 改变驱动器的状态
var                        //devindex : 驱动器索引  newstate : 网卡 的新状态 enable ;启用
    DeviceInfoSet: HDEVINFO;                                      // disable ;禁用
    DeviceInfoData: SP_DEVINFO_DATA;
    PropChangeParams: SP_PROPCHANGE_PARAMS;
    Cursor: HCURSOR;
begin
    Result:=False;

    DeviceInfoSet:=SetupDiGetClassDevs(Nil,Nil,0,DIGCF_ALLCLASSES or DIGCF_PRESENT);  //获得当前驱动器的指针
    if DeviceInfoSet = Pointer(INVALID_HANDLE_VALUE) then
      Exit;

    try
      PropChangeParams.ClassInstallHeader.cbSize:=SizeOf(SP_CLASSINSTALL_HEADER);
      DeviceInfoData.cbSize:=SizeOf(SP_DEVINFO_DATA);

      Cursor := SetCursor(LoadCursor(0, IDC_WAIT));

      if not SetupDiEnumDeviceInfo(DeviceInfoSet,DevIndex,@DeviceInfoData) then
        Exit;

      /////可以对设备进行重启,停止,启动等操作
      PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
      PropChangeParams.Scope := DICS_FLAG_GLOBAL;
      PropChangeParams.StateChange := NewState;

      if not SetupDiSetClassInstallParams(DeviceInfoSet,@DeviceInfoData,
          @PropChangeParams,Sizeof(PropChangeParams)) then
        Exit;

      if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,DeviceInfoSet,
          @DeviceInfoData) then
        Exit;

      SetCursor(Cursor);
      Result:=True;
    finally
      SetupDiDestroyDeviceInfoList(DeviceInfoSet);
    end;
end;

procedure TDevForm.FormCreate(Sender: TObject);
begin
    btRefresh.Click;
end;

procedure TDevForm.btExitClick(Sender: TObject);
begin
  Close;
end;

procedure TDevForm.btApplyClick(Sender: TObject);    //应用 设置
var
    i: Integer;
begin
    for i:=0 to clbDevList.Count-1 do
    begin
        if clbDevList.Checked[i] <> DevState[i] then  //网卡的新状态和原来不一致就判断网卡的新状态是否被选中
        begin
            if clbDevList.Checked[i] then
              ChangeDevState(Cardinal(clbDevList.Items.Objects[i]),DICS_ENABLE)  //启用网卡(cardinal 32位无符号数)
            else
              ChangeDevState(Cardinal(clbDevList.Items.Objects[i]),DICS_DISABLE);  //禁用网卡
        end;
    end;
    RefreshDevState;
end;

procedure TDevForm.RefreshDevState;
var
    i: Integer;
begin
    SetLength(DevState,clbDevList.Count);
    for i:=0 to clbDevList.Count-1 do
      DevState[i]:=clbDevList.Checked[i];
end;

procedure TDevForm.btRefreshClick(Sender: TObject);     //获得网卡信息并且存入 D E V S T A T E的布尔型数组里
begin
    EnumNetDevice;
    RefreshDevState;
end;

end.  
原文地址:https://www.cnblogs.com/MaxWoods/p/453632.html