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


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

    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.  
  • 相关阅读:
    Android Camera Api的心得
    apache禁止訪问某些文件或文件夹的方法
    查询和删除数据表中反复数据的sql
    设计模式C++实现——外观模式
    排序(杭电1106)
    《JAVA程序设计》实训第一天——《猜猜看》游戏
    CSS3选择器(全)
    【原创】TCP超时重传机制探索
    使用Win32 API实现生产者消费者线程同步
    翻翻git之---溜的飞起的载入效果AVLoadingIndicatorView
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/453632.html
Copyright © 2020-2023  润新知