程式讀取電腦裝置管理員中各裝置的狀態(啟用/禁用)?(轉自大富翁)

來源:互聯網
上載者:User
此部分代碼請大家給加上注釋。

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.  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.