程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 用Delphi通過SetupAPI.dll列舉和停用硬件設備

用Delphi通過SetupAPI.dll列舉和停用硬件設備

編輯:Delphi

前天弄的東西,通過SetupAPI.dll列舉硬件設備,部分是改自MSDN自帶的例子,自己加了顯示設備類型名和圖標.代碼是我一個個加上去的有些亂.

{Setup.pas---從SetupAPI.h裡轉的一些函數和常量}
unit SetupAPI;
interface
uses
Windows;
const
DIGCF_PRESENT = $0002;
DIGCF_ALLCLASSES = $0004;
SPDRP_DEVICEDESC = 0;
DIF_PROPERTYCHANGE = 18;
DICS_ENABLE = 1;
DICS_FLAG_GLOBAL = 1;
DICS_DISABLE = 2;
type
HDEVINFO = type Cardinal;
DI_FUNCTION = type Cardinal;
PSP_DEVINFO_DATA = ^SP_DEVINFO_DATA;
SP_DEVINFO_DATA = record
cbSize: DWORD;
ClassGuid: TGUID;
DevInst: DWORD;
Reserved: Longint;
end;
PSP_CLASSINSTALL_HEADER = ^SP_CLASSINSTALL_HEADER;
SP_CLASSINSTALL_HEADER = record
cbSize: DWORD;
InstallFunction: DI_FUNCTION; { (DIF code) }
end;
PSP_PROPCHANGE_PARAMS = ^SP_PROPCHANGE_PARAMS;
SP_PROPCHANGE_PARAMS = record
ClassInstallHeader: SP_CLASSINSTALL_HEADER;
StateChange: DWORD;
Scope: DWORD;
HwProfile: DWORD;
end;
PSP_CLASSIMAGELIST_DATA = ^SP_CLASSIMAGELIST_DATA;
SP_CLASSIMAGELIST_DATA = record
cbSize: DWORD;
ImageList: HWND;
Reserved: DWORD;
end;
function SetupDiGetClassDevs(const ClassGuid: PGUID; Enumerator: PChar;
hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall;
external 'Setupapi.dll' name 'SetupDiGetClassDevsA';
function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD;
DeviceInfoData: PSP_DEVINFO_DATA): BOOL; stdcall;
external 'Setupapi.dll' name 'SetupDiEnumDeviceInfo';
function SetupDiGetDeviceRegistryProperty(DeviceInfoSet: HDEVINFO;
DeviceInfoData: PSP_DEVINFO_DATA; Propertys: DWORD; PropertyRegDataType: PWORD;
PropertyBuffer: PByte; PropertyBufferSize: DWORD; RequiredSize: PWORD): BOOL; stdcall;
external 'Setupapi.dll' name 'SetupDiGetDeviceRegistryPropertyA';
function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): BOOL; stdcall;
external 'Setupapi.dll' name 'SetupDiDestroyDeviceInfoList';
function SetupDiClassNameFromGuid(ClassGuid: PGUID; ClassName: PChar;
ClassNameSize: DWORD; RequiredSize: PDWORD): BOOL; stdcall;
external 'Setupapi.dll' name 'SetupDiClassNameFromGuidA';
function SetupDiSetClassInstallParams(DeviceInfoSet: HDEVINFO ;
DeviceInfoData: PSP_DEVINFO_DATA; ClassInstallParams: PSP_CLASSINSTALL_HEADER;
ClassInstallParamsSize: DWORD): BOOL stdcall;
external 'Setupapi.dll' name 'SetupDiSetClassInstallParamsA';
function SetupDiCallClassInstaller(InstallFunction: DI_FUNCTION;
DeviceInfoSet: HDEVINFO; DeviceInfoData: PSP_DEVINFO_DATA): BOOL; stdcall;
external 'Setupapi.dll' name 'SetupDiCallClassInstaller';
function SetupDiGetClassImageList(ClassImageListData: PSP_CLASSIMAGELIST_DATA): BOOL;
stdcall; external 'Setupapi.dll' name 'SetupDiGetClassImageList';
function SetupDiDestroyClassImageList(ClassImageListData: PSP_CLASSIMAGELIST_DATA):
BOOL; stdcall; external 'Setupapi.dll' name 'SetupDiDestroyClassImageList';
function SetupDiGetClassImageIndex(ClassImageListData: PSP_CLASSIMAGELIST_DATA;
ClassGuid: PGUID; ImageIndex: PINT): BOOL; stdcall;
external 'Setupapi.dll' name 'SetupDiGetClassImageIndex';
implementation
end.
{ untMain.pas主窗體單元,Uses部分引用上面的pas,
再加1個BUTTON;1個TListView;1個TImageList,定義看代碼 }
unit untMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SetupAPI, StdCtrls, ComCtrls, ImgList;
type
TForm1 = class(TForm)
lv1: TListView;
btn1: TButton;
il1: TImageList;
procedure btn1Click(Sender: TObject);
private
function GetDeviceClassName(aGUID: TGUID): string;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
ClassImageListData: SP_CLASSIMAGELIST_DATA; {設備類型圖標結構,全局變量,退出時釋放.}
implementation
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
var
hDevInfo: Cardinal;
DeviceInfoData: SP_DEVINFO_DATA; {設備信息結構}
i: Integer;
DataT, Buffersize: DWORD;
Buffer: PAnsiChar;
List: TListItem;
index: Integer;
begin
{ 獲取設備信息句柄 }
lv1.Items.BeginUpdate;
DriverInfoData.cbSize := SizeOf(SP_DRVINFO_DATA_A);
hDevInfo := SetupDiGetClassDevs(nil, 0, 0,
DIGCF_PRESENT or DIGCF_ALLCLASSES);
if hDevInfo = INVALID_HANDLE_VALUE then Exit;
{ 設備圖標數據結構 }
ClassImageListData.cbSize := SizeOf(SP_CLASSIMAGELIST_DATA);
{ 獲取設備圖標數據 }
if SetupDiGetClassImageList(@ClassImageListData) then
begin
{ 賦句柄給ImageList }
il1.Handle := ClassImageListData.ImageList;
{ TreeView圖標指定到ImageList }
lv1.SmallImages := il1;
end;
i := 0;
Buffersize := 256;
DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
GetMem(Buffer, Buffersize);
{ 枚舉設備信息 }
while SetupDiEnumDeviceInfo(hDevInfo, i, @DeviceInfoData) do
begin
{ 獲取設備信息包括GUID和名稱 }
SetupDiGetDeviceRegistryProperty(hDevInfo, @DeviceInfoData,
SPDRP_DEVICEDESC, @DataT, PByte(Buffer), Buffersize, nil);
Inc(i);
List := lv1.Items.Add;
{ 獲取制定GUID(設備類型)的圖標索引 }
if SetupDiGetClassImageIndex(@ClassImageListData,
@DeviceInfoData.ClassGuid, @index) then
{ 制定顯示圖標 }
List.ImageIndex := index;
{ 通過GUID獲取設備類型(Class) }
List.Caption := GetDeviceClassName(DeviceInfoData.ClassGuid);
{ 轉換GUID到字符串 }
List.SubItems.Add(GUIDToString(DeviceInfoData.ClassGuid));
{ 顯示設備名稱 }
List.SubItems.Add(Buffer);
{ 設備狀態 }
if IsDisableable(i ,hDevInfo) then
List.SubItems.Add('True')
else
List.SubItems.Add('False');
end;
if Buffer <> nil then FreeMem(Buffer);
if (GetLastError() <> NO_ERROR) and
(GetLastError() <> ERROR_NO_MORE_ITEMS) then
Exit;
{ 釋放 DeviceInfoData, hDevInfo }
SetupDiDestroyDeviceInfoList(hDevInfo);
lv1.Items.EndUpdate;
end;
{最後在退出程序時釋放 SetupDiDestroyClassImageList(@ClassImageListData); }
{ 獲取設備類型 }
function TForm1.GetDeviceClassName(aGUID: TGUID): string;
var
ClassName: PChar;
ClassNameSize: DWORD;
begin
ClassNameSize := 0;
GetMem(ClassName, ClassNameSize);
{ 利用GUID返回設備類型名 }
while not SetupDiClassNameFromGuid(@aGUID, ClassName, ClassNameSize,
@ClassNameSize) do
begin
if GetLastError() = ERROR_INSUFFICIENT_BUFFER then
begin
if ClassName <> nil then FreeMem(ClassName);
GetMem(ClassName, ClassNameSize);
end else
Break;
end;
Result := ClassName;
if ClassName <> nil then FreeMem(ClassName);
end;
end.
{設備禁用的代碼,是從網上改些一個C++代碼的,還沒來得及加注解,先看著,以後加.}
function ChangeDeviceState(hDevInfo: HDEVINFO; NewStatus: DWORD;
SelectedItem: DWORD): Boolean;
var
PropChangeParams: SP_PROPCHANGE_PARAMS;
DeviceInfoData: SP_DEVINFO_DATA;
begin
Result := False;
DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
if not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, @DeviceInfoData) then Exit;
// Set the PropChangeParams structure.
PropChangeParams.ClassInstallHeader.cbSize := SizeOf(SP_CLASSINSTALL_HEADER);
PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
PropChangeParams.Scope := DICS_FLAG_GLOBAL;
PropChangeParams.StateChange := NewStatus;
if not SetupDiSetClassInstallParams(hDevInfo, @DeviceInfoData,
PSP_CLASSINSTALL_HEADER(@PropChangeParams), SizeOf(PropChangeParams)) then
Exit;
// Call the ClassInstaller and perform the change.
if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo,
@DeviceInfoData) then
Exit;
Result := True;
end;
function ControlDisk(nStatus, nIndex: Integer): Boolean;
var
Guid: TGUID ;
GUIDString: string;
hDevInfo: Cardinal;
i: DWORD;
DeviceInfoData: SP_DEVINFO_DATA;
begin
Result := False;
if (nStatus = -1) then Exit;
ZeroMemory(@Guid, sizeof(TGUID));
case nIndex of
0: // 0 代表軟驅
GUIDString := '{4D36E980-E325-11CE-BFC1-08002BE10318}';
1: // 1 代表光驅
GUIDString := '{4D36E965-E325-11CE-BFC1-08002BE10318}';
2: // 2 代表USB
GUIDString := '{36FC9E60-C465-11CF-8056-444553540000}';
end;
Guid := StringToGUID(GUIDString);
hDevInfo := SetupDiGetClassDevs(@Guid, nil, HWND(nil), DIGCF_PRESENT);
if (hDevInfo = INVALID_HANDLE_VALUE) then Exit;
ZeroMemory(@DeviceInfoData, SizeOf(SP_DEVINFO_DATA));
DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
i := 0;
while SetupDiEnumDeviceInfo(hDevInfo, i, @DeviceInfoData) do
begin
if nStatus = 1 then
Result := ChangeDeviceState(hDevInfo, DICS_ENABLE, i)
else if nStatus = 2 then
Result := ChangeDeviceState(hDevInfo, DICS_DISABLE, i);
Inc(i);
end;
SetupDiDestroyDeviceInfoList(hDevInfo);
end;
{ 調用如下: 禁用光驅: if ControlDisk(DICS_DISABLE, 1) then ShowMessage('成功禁用!'); }
{ 啟用光驅: if ControlDisk(DICS_ENABLE, 1) then ShowMessage('啟用成功!'); }
{ 注意USB要調用2次 ControlDisk(DICS_ENABLE, 2)才能完成啟用. }
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved