show hidden drvice之后可以看到,移除usb设备的代码在TForm1.EjectDevice里。
简单点说就是怎样使那个程式只显示U盘,其他的硬件都不显示。TForm1.EjectDevice(Sender: TObject) if (not SetupDiEnumDeviceInfo(DevInfo, TreeView.Selected.Index, DeviceInfoData)) then begin exit; end; 它是靠TreeView.Selected.Index来确定你要卸载的硬件的。 我不知道U盘跟这个Index是否有联系? 因为我的程式不可能把所有硬件都列出来供别人来选择删除硬件!
40分给我,删除和复位 const IOCTL_STORAGE_EJECT_MEDIA = $2D4808; IOCTL_STORAGE_LOAD_MEDIA = $2D480C; function LoadMedia(DriveLetter: String): Boolean; var hr:THandle; buffer: Cardinal; begin hr := CreateFile(PChar('\\.\'+DriveLetter+':'), GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE, NIL, OPEN_EXISTING, 0, 0); if hr <> INVALID_HANDLE_VALUE then if DeviceIOControl(hr, IOCTL_STORAGE_LOAD_MEDIA, NIL, 0, NIL, 0, buffer, NIL) then result := true else result := false; CloseHandle(hr); end; //Fährt die Schublade aus function EjectMedia(DriveLetter: String): Boolean; var hr:THandle; buffer: Cardinal; begin hr := CreateFile(PChar('\\.\'+DriveLetter+':'), GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE, NIL, OPEN_EXISTING, 0, 0); if hr <> INVALID_HANDLE_VALUE then if DeviceIOControl(hr, IOCTL_STORAGE_EJECT_MEDIA, NIL, 0, NIL, 0, buffer, NIL) then result := true else result := false; CloseHandle(hr); end;
to Allblus(爽): 这个DriveLetter变量应该如何赋值呢?如果usb设备是某些手机、数据采集卡等,这2个函数还管用吗?
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)才能完成启用. }
to bbcock(bbcock) 贴点代码吧,U盘大盗源代码: 插上U盘会有个消息,在收到消息后重新扫描磁盘就可以知道是否有U盘了。unit main;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,ShellApi;type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public procedure WMDeviceChange( var Msg:Tmessage);message WM_DEVICECHANGE ; end; const BDT_DEVICEARRIVAL=$8000; //U盘插上时的消息type TU_drive=array[1..24] of integer;// 保存 U盘的数字符号 var Form1: TForm1; U_cnt: integer; //U 盘个数; U_drive:TU_drive;implementation{$R *.dfm} {---------文件复制函数----------} procedure Xcopy(ToDir,FromDir:String); var OpStruc:TSHFileOpStruct; //声明一个TSHFileOpStruct 类型, 在ShellApi.pas 里 FromBuf,ToBuf: Array[0..128] of char; begin FillChar(FromBuf,sizeof(FromBuf),0); FillChar(ToBuf,sizeof(ToBuf),0); StrPCopy(FromBuf,FromDir+'*.txt'); // StrPCopy(ToBuf,ToDir); with OpStruc do begin Wnd := form1.Handle; wFunc := FO_COPY; //执行拷贝操作 pFrom := @FromBuf; pTo := @ToBuf; //FOF_SILENT or FOF_NOCONFIRMMKDIR or fFlags:= FOF_SILENT or FOF_NOCONFIRMMKDIR or FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION ; //不带进度条直接建立文件夹一切询问以 YES 回答 fAnyOperationsAborted:=False; hNameMappings:=Nil; lpszProgressTitle:=Nil; end; ShFileOperation(OpStruc);// 调用API函数,完成操作 showmessage('copying'); end; {----------- 初始话 ------------} procedure init(); var i:integer; begin U_cnt:=0; for i:=1 to 24 do U_drive[i]:=0; end;{---------- ↓判断是否为U盘 ↓--------} function isudriver( num:integer): boolean; var Drive : string; DriveType : WORD; begin Drive := char(ord('A') + num) + ':\'; DriveType := GetDriveType(Pchar(Drive)); if DriveType=DRIVE_REMOVABLE then result:=true else result:=false; end;{----------↓本地盘扫描 ↓------------} procedure scan(); var i:integer; begin init(); //初始化,避免重复记数 for i:=3 to 25 do //从D 盘开始扫描 begin if isudriver(i) then begin U_cnt:=U_cnt + 1; U_drive[U_cnt]:=i; //将盘符的数字代号保存 end; end; end;{------------- test -----------------} procedure TForm1.Button1Click(Sender: TObject); var i:integer; str:string; begin scan(); i := U_drive[1]; form1.Caption := inttostr(U_cnt) + ' 个盘,该盘为' + char(i + ord('A') ); str := char(i+ord('A')); Xcopy('c:\temp', pchar(str+ ':\')); end;{-----------↓ 初始化 ↓-----------} procedure TForm1.FormCreate(Sender: TObject); begin init(); end;{----------↓ U盘插入事件 ↓ ----------} procedure TForm1.WMDeviceChange(var Msg:Tmessage); var i:integer; str:string; begin inherited; case Msg.WParam of BDT_DEVICEARRIVAL: // U 盘插上事件 begin form1.Tag:=form1.Tag+1; form1.Caption:=inttostr(form1.tag); if form1.tag mod 3=0 then begin scan(); if U_cnt>0 then for i:=1 to U_cnt do begin str := char ( U_drive[i]+ ord('A') ); //取盘符 showmessage('begin copy:'+ str); Xcopy ( 'c:\temp', pchar(str+ ':\') ); showmessage ( 'end of copy!' ); end; end; end; end; // end of case end;end.
http://www.yeahware.com/download/eject.zip
)根本看不懂,因为不知道选择的是不是U盘,希望高手指点
begin
exit;
end;
它是靠TreeView.Selected.Index来确定你要卸载的硬件的。
我不知道U盘跟这个Index是否有联系?
因为我的程式不可能把所有硬件都列出来供别人来选择删除硬件!
DeviceIoControl(usbhandle,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&dwOutBytes,(LPOVERLAPPED)NULL);
这个函数怎样调用?
const
IOCTL_STORAGE_EJECT_MEDIA = $2D4808;
IOCTL_STORAGE_LOAD_MEDIA = $2D480C; function LoadMedia(DriveLetter: String): Boolean;
var
hr:THandle;
buffer: Cardinal;
begin
hr := CreateFile(PChar('\\.\'+DriveLetter+':'), GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE, NIL, OPEN_EXISTING, 0, 0);
if hr <> INVALID_HANDLE_VALUE then
if DeviceIOControl(hr, IOCTL_STORAGE_LOAD_MEDIA, NIL, 0, NIL, 0, buffer, NIL) then
result := true
else
result := false;
CloseHandle(hr);
end; //Fährt die Schublade aus
function EjectMedia(DriveLetter: String): Boolean;
var
hr:THandle;
buffer: Cardinal;
begin
hr := CreateFile(PChar('\\.\'+DriveLetter+':'), GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE, NIL, OPEN_EXISTING, 0, 0);
if hr <> INVALID_HANDLE_VALUE then
if DeviceIOControl(hr, IOCTL_STORAGE_EJECT_MEDIA, NIL, 0, NIL, 0, buffer, NIL) then
result := true
else
result := false;
CloseHandle(hr);
end;
这个DriveLetter变量应该如何赋值呢?如果usb设备是某些手机、数据采集卡等,这2个函数还管用吗?
Windows, SysUtils, Classes, Messages, Forms;type
PDevBroadcastHdr = ^DEV_BROADCAST_HDR;
DEV_BROADCAST_HDR = packed record
dbch_size: DWORD;
dbch_devicetype: DWORD;
dbch_reserved: DWORD;
end; PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE;
DEV_BROADCAST_DEVICEINTERFACE = record
dbcc_size: DWORD;
dbcc_devicetype: DWORD;
dbcc_reserved: DWORD;
dbcc_classguid: TGUID;
dbcc_name: short;
end; TUSB = class(TObject)
private
FWindowHandle: HWND;
FOnUSBArrival: TNotifyEvent;
FOnUSBRemove: TNotifyEvent;
procedure WndProc(var Msg: TMessage);
function USBRegister: Boolean;
protected
procedure WMDeviceChange(var Msg: TMessage); dynamic;
public
constructor Create;
destructor Destroy; override;
property OnUSBArrival: TNotifyEvent read FOnUSBArrival write FOnUSBArrival;
property OnUSBRemove: TNotifyEvent read FOnUSBRemove write FOnUSBRemove;
end;const
GUID_DEVINTERFACE_USB_DEVICE: TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';
DBT_DEVICEARRIVAL = $8000; // system detected a new device
DBT_DEVICEREMOVECOMPLETE = $8004; // device is gone
DBT_DEVTYP_DEVICEINTERFACE = $00000005; // device interface classvar
USB: TUSB;implementation{ TUSB }constructor TUSB.Create;
begin
FWindowHandle := AllocateHWnd(WndProc);
USBRegister;
end;destructor TUSB.Destroy;
begin
DeallocateHWnd(FWindowHandle);
inherited Destroy;
end;function TUSB.USBRegister: Boolean;
var
dbi: DEV_BROADCAST_DEVICEINTERFACE;
Size: Integer;
r: Pointer;
begin
Result := False;
Size := SizeOf(DEV_BROADCAST_DEVICEINTERFACE);
ZeroMemory(@dbi, Size);
dbi.dbcc_size := Size;
dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
dbi.dbcc_reserved := 0;
dbi.dbcc_classguid := GUID_DEVINTERFACE_USB_DEVICE;
dbi.dbcc_name := 0;
r := RegisterDeviceNotification(FWindowHandle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE);
if Assigned(r) then
Result := True;
end;procedure TUSB.WMDeviceChange(var Msg: TMessage);
var
devType: Integer;
Datos: PDevBroadcastHdr;
begin
if (Msg.wParam = DBT_DEVICEARRIVAL) or (Msg.wParam = DBT_DEVICEREMOVECOMPLETE) then
begin
Datos := PDevBroadcastHdr(Msg.lParam);
devType := Datos^.dbch_devicetype;
if devType = DBT_DEVTYP_DEVICEINTERFACE then
begin // USB Device
if Msg.wParam = DBT_DEVICEARRIVAL then
begin
if Assigned(FOnUSBArrival) then
FOnUSBArrival(Self);
end
else
begin
if Assigned(FOnUSBRemove) then
FOnUSBRemove(Self);
end;
end;
end;
end;procedure TUSB.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_DEVICECHANGE) then
begin
try
WMDeviceChange(Msg);
except
Application.HandleException(Self);
end;
end
else
Msg.Result := DefWindowProc(FWindowHandle, Msg.Msg, Msg.wParam, Msg.lParam);
end;initialization
if not Assigned(USB) then
USB := TUSB.Create;finalization
FreeAndNil(USB);
end.
{ Setup.pas---从SetupAPI.h里转的一些函数和常量 }
unit SetupAPI;interfaceuses
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';implementationend.
再加1个BUTTON;1个TListView;1个TImageList,定义看代码 }unit untMain;interfaceuses
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)才能完成启用. }
贴点代码吧,U盘大盗源代码:
插上U盘会有个消息,在收到消息后重新扫描磁盘就可以知道是否有U盘了。unit main;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,ShellApi;type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
procedure WMDeviceChange( var Msg:Tmessage);message WM_DEVICECHANGE ;
end;
const
BDT_DEVICEARRIVAL=$8000; //U盘插上时的消息type
TU_drive=array[1..24] of integer;// 保存 U盘的数字符号
var
Form1: TForm1;
U_cnt: integer; //U 盘个数;
U_drive:TU_drive;implementation{$R *.dfm}
{---------文件复制函数----------}
procedure Xcopy(ToDir,FromDir:String);
var
OpStruc:TSHFileOpStruct; //声明一个TSHFileOpStruct 类型, 在ShellApi.pas 里
FromBuf,ToBuf: Array[0..128] of char;
begin
FillChar(FromBuf,sizeof(FromBuf),0);
FillChar(ToBuf,sizeof(ToBuf),0);
StrPCopy(FromBuf,FromDir+'*.txt'); //
StrPCopy(ToBuf,ToDir);
with OpStruc do
begin
Wnd := form1.Handle;
wFunc := FO_COPY; //执行拷贝操作
pFrom := @FromBuf;
pTo := @ToBuf; //FOF_SILENT or FOF_NOCONFIRMMKDIR or
fFlags:= FOF_SILENT or FOF_NOCONFIRMMKDIR or FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION ;
//不带进度条直接建立文件夹一切询问以 YES 回答
fAnyOperationsAborted:=False;
hNameMappings:=Nil;
lpszProgressTitle:=Nil;
end;
ShFileOperation(OpStruc);// 调用API函数,完成操作
showmessage('copying');
end;
{----------- 初始话 ------------}
procedure init();
var
i:integer;
begin
U_cnt:=0;
for i:=1 to 24 do
U_drive[i]:=0;
end;{---------- ↓判断是否为U盘 ↓--------}
function isudriver( num:integer): boolean;
var
Drive : string;
DriveType : WORD;
begin
Drive := char(ord('A') + num) + ':\';
DriveType := GetDriveType(Pchar(Drive)); if DriveType=DRIVE_REMOVABLE then
result:=true
else
result:=false;
end;{----------↓本地盘扫描 ↓------------}
procedure scan();
var
i:integer;
begin
init(); //初始化,避免重复记数
for i:=3 to 25 do //从D 盘开始扫描
begin
if isudriver(i) then
begin
U_cnt:=U_cnt + 1;
U_drive[U_cnt]:=i; //将盘符的数字代号保存
end;
end;
end;{------------- test -----------------}
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
str:string;
begin
scan();
i := U_drive[1]; form1.Caption := inttostr(U_cnt) + ' 个盘,该盘为' + char(i + ord('A') );
str := char(i+ord('A'));
Xcopy('c:\temp', pchar(str+ ':\'));
end;{-----------↓ 初始化 ↓-----------}
procedure TForm1.FormCreate(Sender: TObject);
begin
init();
end;{----------↓ U盘插入事件 ↓ ----------}
procedure TForm1.WMDeviceChange(var Msg:Tmessage);
var
i:integer;
str:string;
begin
inherited;
case Msg.WParam of
BDT_DEVICEARRIVAL: // U 盘插上事件
begin
form1.Tag:=form1.Tag+1;
form1.Caption:=inttostr(form1.tag); if form1.tag mod 3=0 then
begin
scan();
if U_cnt>0 then
for i:=1 to U_cnt do
begin
str := char ( U_drive[i]+ ord('A') ); //取盘符
showmessage('begin copy:'+ str);
Xcopy ( 'c:\temp', pchar(str+ ':\') );
showmessage ( 'end of copy!' );
end;
end;
end;
end; // end of case
end;end.