使用Delphi检测在Windows中安装卷的时间 [英] Detecting when a volume is mounted in Windows with Delphi

查看:250
本文介绍了使用Delphi检测在Windows中安装卷的时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在MSDN上了解有关设备事件
的文档,以及如何在挂载卷时触发通知。



我已经管理使用以下信息中提供的信息为USB设备执行此操作:检测USB驱动器/设备使用delphi



以及互联网上发现的其他信息,
,但我注意到,当一个卷已被直接安装。



所以我的问题是:如何在我的Delphi应用程序中实现Device Events处理?



我正在查看以下文档: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363217(v = vs85).aspx



但是我真的不知道如何让它运行



到目前为止,我已经尝试了以下代码,它正确编译,
但没有任何反应,请推动我正确的方向:

  PDevBroadcastHdr = ^ DEV_BROADCAST_HDR; 
DEV_BROADCAST_HDR =打包记录
dbch_size:DWORD;
dbch_devicetype:DWORD;
dbch_reserved:DWORD;
结束

PDevBroadcastHandle = ^ DEV_BROADCAST_HANDLE;
DEV_BROADCAST_HANDLE =打包记录
dbch_size:DWORD;
dbch_devicetype:DWORD;
dbch_reserved:DWORD;
dbch_handle:THandle;
dbch_hdevnotify:HDEVNOTIFY;
dbch_eventguid:TGUID;
dbch_nameoffset:LongInt;
dbch_data:byte;
结束

...


程序WMDeviceChange(var Msg:TMessage);

const
DBT_DEVTYP_HANDLE = $ 0006;
GUID_IO_VOLUME_MOUNT:TGUID ='{B5804878-1A96-11D2-8FFD-00A0C9A06D32}';

...

函数TForm1.RegisterThis:Boolean;
var
dbv:DEV_BROADCAST_HANDLE;
大小:整数;
r:指针;
begin
大小:= SizeOf(DEV_BROADCAST_HANDLE);
ZeroMemory(@dbv,Size);
dbv.dbch_size:= Size;
dbv.dbch_devicetype:= DBT_DEVTYP_HANDLE;
dbv.dbch_reserved:= 0;
dbv.dbch_handle:= 0;
dbv.dbch_hdevnotify:= nil;
dbv.dbch_eventguid:= GUID_IO_VOLUME_MOUNT;
dbv.dbch_nameoffset:= 0;
dbv.dbch_data:= 0;

r:= RegisterDeviceNotification(FWindowHandle,@dbv,DEVICE_NOTIFY_WINDOW_HANDLE);


如果已分配(r)则结果:= True;
结束


程序TForm1.WMDeviceChange(var Msg:TMessage);
var
VData:PDevBroadcastHandle;
begin
ShowMessage('Hello!');
结束


解决方案

编辑:找到在这个论坛上的组件。它被称为TSHChangeNotify,并由Elliott Shevinm于2000年回复(!)



在这里查看论坛主题。它包含源代码和修复。
Theres还是由Zarko Gajic撰写的一篇文章,它解释了它的工作原理。
在这里找到



仅在使用VCL时,在Windows 8.1上的Delphi XE7中工作得很好。



更新:我修改了代码,现在可以在带有Firemonkey的Delphi XE7上运行。
可以在这里找到更新的代码。



我设置的方式是将 TSHChangeNotify.HardDriveOnly 设置为 FALSE c code code code $ TS code>在主窗体内放入 TSHChangeNotify.Execute b
$ b




感谢Dalija和David,我收到了一些很好的信息和代码,派上用场。



但是他们的答案没有解决我的问题。



像David在其中一个评论中说的,他只是想推动我正确的方向为我自己在我的问题上提出。



我开始使用guid_io_volume_mount c ++的Google搜索,看看是否可以在其他地方找到可用的代码。



我发现这个论坛帖子: http: //www.mofeel.net/957-microsoft-public-vc-language/2343.aspx



他的代码中提到的OP中CreateFileA应该是用于在安装点发生变化时基本上监控。



安装点似乎是驱动器盘符,例如C :, D :, E:等等...



所以基本上发生的是通过使用以下代码

  var 
dbv:DEV_BROADCAST_HANDLE;
大小:整数;
r:指针;
begin

大小:= SizeOf(DEV_BROADCAST_HANDLE);
ZeroMemory(@dbv,Size);
dbv.dbch_size:= Size;
dbv.dbch_devicetype:= DBT_DEVTYP_HANDLE;
dbv.dbch_reserved:= 0;
dbv.dbch_handle:= CreateFileA('\\.\C:',GENERIC_READ,FILE_SHARE_READ + FILE_SHARE_WRITE,nil,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING + FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN,0);
dbv.dbch_hdevnotify:= 0;
dbv.dbch_nameoffset:= 0;

r:= RegisterDeviceNotification(fHandle,@dbv,DEVICE_NOTIFY_WINDOW_HANDLE);

if Assigned(r)then Result:= True;

我们让操作系统知道,每当C:更改其安装状态(挂载/卸载) ,操作系统将向我们的WndProc消息捕获器发送一条消息。



我的完整源代码可以在下面,仍然有点bug,但它提供了一个概念到目前为止。 p>

至少可以检测何时挂载指定的卷。
当您右键单击卷并选择弹出时,将检测到卸载。



现在记住,此代码可以做的不仅仅是检测何时挂载点已更改,此MSDN文章包含所有GUID的你需要做一些漂亮的东西。

  unit Unit1; 

接口

使用
Winapi.Windows,Winapi.Messages,System.SysUtils,System.Classes,
Vcl.Graphics,Vcl.Controls, Vcl.Forms,Vcl.StdCtrls,Vcl.dialogs;

type
TDeviceDetector = class
protected
fHandle:THandle;
fLogger:TMemo;

fOnCDROM_EXCLUSIVE_LOCK,
fOnCDROM_EXCLUSIVE_UNLOCK,
fOnDEVICE_BECOMING_READY,
fOnDEVICE_EXTERNAL_REQUEST,
fOnMEDIA_ARRIVAL,
fOnMEDIA_EJECT_REQUEST,
fOnMEDIA_REMOVAL,
fOnVOLUME_CHANGE,
fOnVOLUME_CHANGE_SIZE,
fOnVOLUME_DISMOUNT,
fOnVOLUME_DISMOUNT_FAILED,
fOnVOLUME_FVE_STATUS_CHANGE,
fOnVOLUME_LOCK,
fOnVOLUME_LOCK_FAILED,
fOnVOLUME_MOUNT,
fOnVOLUME_NAME_CHANGE,
fOnVOLUME_NEED_CHKDSK,
fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE,
fOnVOLUME_PREPARING_EJECT,
fOnVOLUME_UNIQUE_ID_CHANGE,
fOnVOLUME_UNLOCK,
fOnVOLUME_WEARING_OUT:TNotifyEvent;

程序WndProc(var Message:TMessage);
程序日志(AStr:string);
public
构造函数创建;
析构函数覆盖;
函数RegisterThis:Boolean;
属性记录器:TMemo读取fLogger写入fLogger;
发布
属性OnCDROM_EXCLUSIVE_LOCK:TNotifyEvent读取fOnCDROM_EXCLUSIVE_LOCK写入fOnCDROM_EXCLUSIVE_LOCK;
属性OnCDROM_EXCLUSIVE_UNLOCK:TNotifyEvent读取fOnCDROM_EXCLUSIVE_UNLOCK写入fOnCDROM_EXCLUSIVE_UNLOCK;
属性OnDEVICE_BECOMING_READY:TNotifyEvent读取fOnDEVICE_BECOMING_READY写入fOnDEVICE_BECOMING_READY;
属性OnDEVICE_EXTERNAL_REQUEST:TNotifyEvent读取fOnDEVICE_EXTERNAL_REQUEST写入fOnDEVICE_EXTERNAL_REQUEST;
属性OnMEDIA_ARRIVAL:TNotifyEvent read fOnMEDIA_ARRIVAL write fOnMEDIA_ARRIVAL;
属性OnMEDIA_EJECT_REQUEST:TNotifyEvent读取fOnMEDIA_EJECT_REQUEST写入fOnMEDIA_EJECT_REQUEST;
属性OnMEDIA_REMOVAL:TNotifyEvent read fOnMEDIA_REMOVAL write fOnMEDIA_REMOVAL;
属性OnVOLUME_CHANGE:TNotifyEvent读取fOnVOLUME_CHANGE写入fOnVOLUME_CHANGE;
属性OnVOLUME_CHANGE_SIZE:TNotifyEvent读取fOnVOLUME_CHANGE_SIZE写入fOnVOLUME_CHANGE_SIZE;
属性OnVOLUME_DISMOUNT:TNotifyEvent读取fOnVOLUME_DISMOUNT写入fOnVOLUME_DISMOUNT;
属性OnVOLUME_DISMOUNT_FAILED:TNotifyEvent读取fOnVOLUME_DISMOUNT_FAILED写入fOnVOLUME_DISMOUNT_FAILED;
属性OnVOLUME_FVE_STATUS_CHANGE:TNotifyEvent读取fOnVOLUME_FVE_STATUS_CHANGE写入fOnVOLUME_FVE_STATUS_CHANGE;
属性OnVOLUME_LOCK:TNotifyEvent读取fOnVOLUME_LOCK写入fOnVOLUME_LOCK;
属性OnVOLUME_LOCK_FAILED:TNotifyEvent读取fOnVOLUME_LOCK_FAILED写入fOnVOLUME_LOCK_FAILED;
属性OnVOLUME_MOUNT:TNotifyEvent读取fOnVOLUME_MOUNT写入fOnVOLUME_MOUNT;
属性OnVOLUME_NAME_CHANGE:TNotifyEvent read fOnVOLUME_NAME_CHANGE write fOnVOLUME_NAME_CHANGE;
属性OnVOLUME_NEED_CHKDSK:TNotifyEvent读取fOnVOLUME_NEED_CHKDSK写入fOnVOLUME_NEED_CHKDSK;
属性OnVOLUME_PHYSICAL_CONFIGURATION_CHANGE:TNotifyEvent read fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE write fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE;
属性OnVOLUME_PREPARING_EJECT:TNotifyEvent读取fOnVOLUME_PREPARING_EJECT写入fOnVOLUME_PREPARING_EJECT;
属性OnVOLUME_UNIQUE_ID_CHANGE:TNotifyEvent读取fOnVOLUME_UNIQUE_ID_CHANGE写入fOnVOLUME_UNIQUE_ID_CHANGE;
属性OnVOLUME_UNLOCK:TNotifyEvent读取fOnVOLUME_UNLOCK写入fOnVOLUME_UNLOCK;
属性OnVOLUME_WEARING_OUT:TNotifyEvent读取fOnVOLUME_WEARING_OUT写入fOnVOLUME_WEARING_OUT;
结束

TForm1 = class(TForm)
Memo1:TMemo;
procedure FormCreate(Sender:TObject);
procedure FormDestroy(Sender:TObject);
private
end;

var
Form1:TForm1;
dd:TDeviceDetector;

实现

{$ R * .dfm}

类型
PDevBroadcastHdr = ^ DEV_BROADCAST_HDR;
DEV_BROADCAST_HDR =打包记录
dbch_size:DWORD;
dbch_devicetype:DWORD;
dbch_reserved:DWORD;
结束

PDevBroadcastHandle = ^ DEV_BROADCAST_HANDLE;
DEV_BROADCAST_HANDLE = record
dbch_size:DWORD;
dbch_devicetype:DWORD;
dbch_reserved:DWORD;
dbch_handle:THandle;
dbch_hdevnotify:HDEVNOTIFY;
dbch_eventguid:TGUID;
dbch_nameoffset:LONG;
dbch_data:字节数组[0..0];
结束

const
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = $ 00000004;

DBT_CUSTOMEVENT = $ 8006;
DBT_DEVTYP_HANDLE = $ 0006;

GUID_IO_CDROM_EXCLUSIVE_LOCK:TGUID ='{bc56c139-7a10-47ee-a294-4c6a38f0149a}';
GUID_IO_CDROM_EXCLUSIVE_UNLOCK:TGUID ='{a3b6d27d-5e35-4885-81e5-ee18c00ed779}';
GUID_IO_DEVICE_BECOMING_READY:TGUID ='{d07433f0-a98e-11d2-917a-00a0c9068ff3}';
GUID_IO_DEVICE_EXTERNAL_REQUEST:TGUID ='{d07433d0-a98e-11d2-917a-00a0c9068ff3}';
GUID_IO_MEDIA_ARRIVAL:TGUID ='{d07433c0-a98e-11d2-917a-00a0c9068ff3}';
GUID_IO_MEDIA_EJECT_REQUEST:TGUID ='{d07433d1-a98e-11d2-917a-00a0c9068ff3}';
GUID_IO_MEDIA_REMOVAL:TGUID ='{d07433c1-a98e-11d2-917a-00a0c9068ff3}';
GUID_IO_VOLUME_CHANGE:TGUID ='{7373654a-812a-11d0-bec7-08002be2092f}';
GUID_IO_VOLUME_CHANGE_SIZE:TGUID ='{3a1625be-ad03-49f1-8ef8-6bbac182d1fd}';
GUID_IO_VOLUME_DISMOUNT:TGUID ='{d16a55e8-1059-11d2-8ffd-00a0c9a06d32}';
GUID_IO_VOLUME_DISMOUNT_FAILED:TGUID ='{E3C5B178-105D-11D2-8FFD-00A0C9A06D32}';
GUID_IO_VOLUME_FVE_STATUS_CHANGE:TGUID ='{062998b2-ee1f-4b6a-b857-e76cbbe9a6da}';
GUID_IO_VOLUME_LOCK:TGUID ='{50708874-c9af-11d1-8fef-00a0c9a06d32}';
GUID_IO_VOLUME_LOCK_FAILED:TGUID ='{ae2eed10-0ba8-11d2-8ffb-00a0c9a06d32}';
GUID_IO_VOLUME_MOUNT:TGUID ='{b5804878-1a96-11d2-8ffd-00a0c9a06d32}';
GUID_IO_VOLUME_NAME_CHANGE:TGUID ='{2de97f83-4c06-11d2-a532-00609713055a}';
GUID_IO_VOLUME_NEED_CHKDSK:TGUID ='{799a0960-0a0b-4e03-ad88-2fa7c6ce748a}';
GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE:TGUID ='{2de97f84-4c06-11d2-a532-00609713055a}';
GUID_IO_VOLUME_PREPARING_EJECT:TGUID ='{c79eb16e-0dac-4e7a-a86c-b25ceeaa88f6}';
GUID_IO_VOLUME_UNIQUE_ID_CHANGE:TGUID ='{af39da42-6622-41f5-970b-139d092fa3d9}';
GUID_IO_VOLUME_UNLOCK:TGUID ='{9a8c3d68-d0cb-11d1-8fef-00a0c9a06d32}';
GUID_IO_VOLUME_WEARING_OUT:TGUID ='{873113ca-1486-4508-82ac-c3b2e5297aaa}';




函数WDE_GUID_To_String(AGUID:TGUID):string; // WDE代表Windows设备事件
begin
如果AGUI​​D = GUID_IO_CDROM_EXCLUSIVE_LOCK然后result:='GUID_IO_CDROM_EXCLUSIVE_LOCK'else
如果AGUI​​D = GUID_IO_CDROM_EXCLUSIVE_UNLOCK然后result:='GUID_IO_CDROM_EXCLUSIVE_UNLOCK'else
if AGUID = GUID_IO_DEVICE_BECOMING_READY then result:='GUID_IO_DEVICE_BECOMING_READY'else
如果AGUI​​D = GUID_IO_DEVICE_EXTERNAL_REQUEST然后result:='GUID_IO_DEVICE_BECOMING_READY'else
如果AGUI​​D = GUID_IO_MEDIA_ARRIVAL然后result:='GUID_IO_MEDIA_ARRIVAL'else
如果AGUI​​D = GUID_IO_MEDIA_EJECT_REQUEST然后结果:='GUID_IO_MEDIA_EJECT_REQUEST'else
如果AGUI​​D = GUID_IO_MEDIA_REMOVAL,则result:='GUID_IO_MEDIA_REMOVAL'else
如果AGUI​​D = GUID_IO_VOLUME_CHANGE然后result:='GUID_IO_VOLUME_CHANGE'else
如果AGUI​​D = GUID_IO_VOLUME_CHANGE_SIZE则结果:='G UID_IO_VOLUME_CHANGE_SIZE别的
如果AGUI​​D = GUID_IO_VOLUME_DISMOUNT则导致:= 'GUID_IO_VOLUME_DISMOUNT' 如果AGUI​​D = GUID_IO_VOLUME_DISMOUNT_FAILED然后别的
结果:= 'GUID_IO_VOLUME_DISMOUNT_FAILED' 别的
如果AGUI​​D = GUID_IO_VOLUME_FVE_STATUS_CHANGE则导致:= 'GUID_IO_VOLUME_FVE_STATUS_CHANGE'否则
如果AGUI​​D = GUID_IO_VOLUME_LOCK然后result:='GUID_IO_VOLUME_LOCK'else
如果AGUI​​D = GUID_IO_VOLUME_LOCK_FAILED然后result:='GUID_IO_VOLUME_LOCK_FAILED'else
如果AGUI​​D = GUID_IO_VOLUME_MOUNT然后result:='GUID_IO_VOLUME_MOUNT'else
如果AGUI​​D = GUID_IO_VOLUME_NAME_CHANGE然后result:='GUID_IO_VOLUME_NAME_CHANGE'else
如果AGUI​​D = GUID_IO_VOLUME_NEED_CHKDSK然后result:='GUID_IO_VOLUME_NEED_CHKDSK'else

如果AGUI​​D = GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE然后结果:= 'GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE' 别的

如果AGUI​​D = GUID_IO_VOLUME_PREPARING_EJECT则导致:= 'GUID_IO_VOLUME_PREPARING_EJECT' 别的
如果AGUI​​D = GUID_IO_VOLUME_UNIQUE_ID_CHANGE则导致:= 'GUID_IO_VOLUME_UNIQUE_ID_CHANGE' 别的
如果AGUI​​D = GUID_IO_VOLUME_UNLOCK那么结果:='GUID_IO_VOLUME_UNLOCK'else
如果AGUI​​D = GUID_IO_VOLUME_WEARING_OUT然后result:='GUID_IO_VOLUME_WEARING_OUT';
结束



构造函数TDeviceDetector.Create;
开始
继承;
fHandle:= AllocateHWnd(WndProc);
结束

析构函数TDeviceDetector.Destroy;
begin
DeallocateHWnd(fHandle);
继承;
结束

函数TDeviceDetector.RegisterThis:Boolean;
var
dbv:DEV_BROADCAST_HANDLE;
大小:整数;
r:指针;
begin
大小:= SizeOf(DEV_BROADCAST_HANDLE);
ZeroMemory(@dbv,Size);
dbv.dbch_size:= Size;
dbv.dbch_devicetype:= DBT_DEVTYP_HANDLE;
dbv.dbch_reserved:= 0;
dbv.dbch_handle:= CreateFileA('\\.\E:',GENERIC_READ,FILE_SHARE_READ + FILE_SHARE_WRITE,nil,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING + FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN,0);
dbv.dbch_hdevnotify:= RegisterDeviceNotification(fHandle,@dbv,DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);;
dbv.dbch_nameoffset:= 0;


如果已分配(dbv.dbch_hdevnotify),则结果:= True;
结束

程序TDeviceDetector.WndProc(var Message:TMessage);
var data:PDevBroadcastHdr;
data_H:PDevBroadcastHandle;
begin
如果Message.wParam = DBT_CUSTOMEVENT然后//根据MSDN,DEV_BROADCAST_HANDLE结构被视为一个自定义事件。
begin
数据:= PDevBroadcastHdr(Message.LParam); //我们需要处理这个自定义的第一个DEV_BROADCAST_HDR结构...

如果Data ^ .dbch_devicetype = DBT_DEVTYP_HANDLE然后//然后我们检查设备类型是DBT_DEVTYP_HANDLE
begin
data_H:= PDevBroadcastHandle(Message.lParam); //如果设备类型为DBT_DEVTYP_HANDLE,我们将自定义事件视为DEV_BROADCAST_HANDLE结构

//最后一步是查看结构DEV_BROADCAST_HANDLE的事件是什么GUID

日志(WDE_GUID_To_String(data_H ^ .dbch_eventguid));

如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_CDROM_EXCLUSIVE_LOCK)= true则分配(fOnCDROM_EXCLUSIVE_LOCK)然后fOnCDROM_EXCLUSIVE_LOCK(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_CDROM_EXCLUSIVE_UNLOCK)= true,那么if (fOnDEVICE_BECOMING_READY)然后fOnDEVICE_BECOMING_READY(self)else f $ n
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_DEVICE_BECOMING_READY)= true,则分配(fOnDEVICE_BECOMING_READY) GUID_IO_DEVICE_EXTERNAL_REQUEST)= true然后如果分配(fOnDEVICE_EXTERNAL_REQUEST),则fOnDEVICE_EXTERNAL_REQUEST(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_MEDIA_ARRIVAL)= true,那么如果分配(fOnMEDIA_ARRIVAL)则fOnMEDIA_ARRIVAL(self)else
如果IsEqualGUID (data_H ^ .dbch_eventguid,GUID_IO_MEDIA_EJECT_REQU EST)= true然后如果分配(fOnMEDIA_EJECT_REQUEST)则fOnMEDIA_EJECT_REQUEST(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_MEDIA_REMOVAL)= true,那么如果分配(fOnMEDIA_REMOVAL)则fOnMEDIA_REMOVAL(self)else
if IsEqualGUID (data_H ^ .dbch_eventguid,GUID_IO_VOLUME_CHANGE)= true然后如果分配(fOnVOLUME_CHANGE)然后fOnVOLUME_CHANGE(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_CHANGE_SIZE)= true,那么如果分配(fOnVOLUME_CHANGE_SIZE)则fOnVOLUME_CHANGE_SIZE(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_DISMOUNT)= true,那么如果分配(fOnVOLUME_DISMOUNT)则fOnVOLUME_DISMOUNT(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_DISMOUNT_FAILED)= true,那么如果分配(fOnVOLUME_DISMOUNT_FAILED)然后fOnVOLUME_ DISMOUNT_FAILED(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_FVE_STATUS_CHANGE)= true,那么如果分配(fOnVOLUME_FVE_STATUS_CHANGE)则fOnVOLUME_FVE_STATUS_CHANGE(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_LOCK)= true如果分配了(fOnVOLUME_LOCK),则fOnVOLUME_LOCK(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_LOCK_FAILED)= true,则分配(fOnVOLUME_LOCK_FAILED)然后fOnVOLUME_LOCK_FAILED(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid ,GUID_IO_VOLUME_MOUNT)= true然后如果分配(fOnVOLUME_MOUNT)然后fOnVOLUME_MOUNT(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_NAME_CHANGE)= true,那么如果分配(fOnVOLUME_NAME_CHANGE)然后fOnVOLUME_NAME_CHANGE(self)else
if IsEqualGUID(data_H ^ .dbch_eventguid, GUID_IO_VOLUME_NEED_CHKDSK)如果分配(fOnVOLUME_NEED_CHKDSK)= true,那么则fOnVOLUME_NEED_CHKDSK(个体经营)否则
如果要是分配(fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE)然后fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE(个体经营)否则
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE)= true,那么IsEqualGUID (data_H ^ .dbch_eventguid,GUID_IO_VOLUME_PREPARING_EJECT)如果分配(fOnVOLUME_PREPARING_EJECT)然后fOnVOLUME_PREPARING_EJECT(个体经营)否则
如果分配(fOnVOLUME_UNIQUE_ID_CHANGE)然后fOnVOLUME_UNIQUE_ID_CHANGE(个体经营)如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_UNIQUE_ID_CHANGE)= true,则=真那么其他
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_UNLOCK)= true,那么如果分配(fOnVOLUME_UNLOCK)则fOnVOLUME_UNLOCK(self)else
如果IsEqualGUID(data_H ^ .dbch_eventguid,GUID_IO_VOLUME_WEARING_OUT)= true如果分配(fOnVOLUME_WEARING_OUT),则fOnVOLUME_WEARING_OUT(self);
结束

end;
结束

程序TDeviceDetector.Log(AStr:string);
begin
fLogger.Lines.Add(AStr);
结束

procedure TForm1.FormCreate(Sender:TObject);
begin
dd:= TDeviceDetector.Create;
dd.Logger:= Memo1;
如果dd.RegisterThis = true,那么Memo1.Lines.Add('Registered!')else Memo1.Lines.Add('Failed to register!');
结束

procedure TForm1.FormDestroy(Sender:TObject);
begin
dd.free;
结束


结束。


I am trying to understand the documentation at MSDN regarding Device Events and how to trigger a notification whenever a volume has been mounted.

I have managed to do this for USB devices using information presented in the following post: detect usb drive/device using delphi

as well as other information found on the internet, but I have noticed that it would be easier to detect when a volume has been mounted directly.

So my question is: how do I implement Device Events handling in my Delphi app?

I am looking at the following documentation: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363217(v=vs.85).aspx

But I can't really figure out how to get it up and running.

So far I have tried the following code, which compiles properly, but nothing happens, please push me in the right direction:

PDevBroadcastHdr  = ^DEV_BROADCAST_HDR;
  DEV_BROADCAST_HDR = packed record
    dbch_size       : DWORD;
    dbch_devicetype : DWORD;
    dbch_reserved   : DWORD;
  end;

  PDevBroadcastHandle = ^DEV_BROADCAST_HANDLE;
  DEV_BROADCAST_HANDLE = packed record
    dbch_size       : DWORD       ;
    dbch_devicetype : DWORD       ;
    dbch_reserved   : DWORD       ;
    dbch_handle     : THandle     ;
    dbch_hdevnotify : HDEVNOTIFY  ;
    dbch_eventguid  : TGUID       ;
    dbch_nameoffset : LongInt     ;
    dbch_data       : byte        ;
  end;

...


procedure WMDeviceChange(var Msg: TMessage);

const
  DBT_DEVTYP_HANDLE = $0006;
  GUID_IO_VOLUME_MOUNT: TGUID = '{B5804878-1A96-11D2-8FFD-00A0C9A06D32}';

...

function TForm1.RegisterThis: Boolean;
var
  dbv: DEV_BROADCAST_HANDLE;
  Size: Integer;
  r: Pointer;
begin
  Size := SizeOf(DEV_BROADCAST_HANDLE);
  ZeroMemory(@dbv, Size);
  dbv.dbch_size := Size;
  dbv.dbch_devicetype := DBT_DEVTYP_HANDLE;
  dbv.dbch_reserved := 0;
  dbv.dbch_handle  := 0;
  dbv.dbch_hdevnotify := nil;
  dbv.dbch_eventguid := GUID_IO_VOLUME_MOUNT;
  dbv.dbch_nameoffset := 0;
  dbv.dbch_data := 0;

  r := RegisterDeviceNotification(FWindowHandle, @dbv, DEVICE_NOTIFY_WINDOW_HANDLE);


  if Assigned(r) then Result := True;
end;


procedure TForm1.WMDeviceChange(var Msg: TMessage);
var
  VData: PDevBroadcastHandle;
begin
  ShowMessage('Hello!');
end;

解决方案

EDIT: Found a component on a forum regarding this. It is called TSHChangeNotify and was written by Elliott Shevinm back in 2000 (!)

See the forum thread here. It contains the sourcecode and a fix. Theres also an article written by Zarko Gajic which explains how it works found here

It works perfectly fine in Delphi XE7 on Windows 8.1 when using VCL only.

UPDATE: I modified the code so it now runs on Delphi XE7 with Firemonkey. The updated code can be found here.

The way I set it up is by setting TSHChangeNotify.HardDriveOnly to FALSE and putting TSHChangeNotify.Execute inside main forms OnCreate procedure.


Thanks to Dalija and David, I received some good information and code which came in handy.

However their answers did not solve my problem.

Like David said in one of the comments, he just wanted to "push me in the right direction" as I myself suggested in my question. Fair enough.

I started Googling for "guid_io_volume_mount c++" to see if I could find some usable code elsewhere that I could port.

I came across this forum post: http://www.mofeel.net/957-microsoft-public-vc-language/2343.aspx

The OP mentioned in his code that CreateFileA should be used in order to basically "monitor" whenever a mount point has changed.

A mount point seems to be the drive letter, for example C:, D:, E: etc...

So basically what happens is that by using the following code

var
  dbv: DEV_BROADCAST_HANDLE;
  Size: Integer;
  r: Pointer;
begin

  Size := SizeOf(DEV_BROADCAST_HANDLE);
  ZeroMemory(@dbv, Size);
  dbv.dbch_size := Size;
  dbv.dbch_devicetype := DBT_DEVTYP_HANDLE;
  dbv.dbch_reserved := 0;
  dbv.dbch_handle  := CreateFileA('\\.\C:', GENERIC_READ, FILE_SHARE_READ+FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING + FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0);
  dbv.dbch_hdevnotify := 0;
  dbv.dbch_nameoffset := 0;

  r := RegisterDeviceNotification(fHandle, @dbv, DEVICE_NOTIFY_WINDOW_HANDLE);

  if Assigned(r) then Result := True;

we let the OS know that whenever "C:" has changed its mount state (mount/dismount), the OS will send a message to our WndProc message catcher.

My full source is avaible below, still a bit buggy, but it presents a concept so far.

It can detect when a specified volume is mounted, at least. Dismount is detected when you right click on a volume and select "Eject".

Now remember, this code can do more than just detecting when mount points are changed, this MSDN article has all the GUID's you need to do some pretty neat stuff.

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls, Vcl.dialogs;

type
  TDeviceDetector = class
  protected
    fHandle: THandle;
    fLogger: TMemo;

    fOnCDROM_EXCLUSIVE_LOCK      ,
    fOnCDROM_EXCLUSIVE_UNLOCK    ,
    fOnDEVICE_BECOMING_READY     ,
    fOnDEVICE_EXTERNAL_REQUEST   ,
    fOnMEDIA_ARRIVAL             ,
    fOnMEDIA_EJECT_REQUEST       ,
    fOnMEDIA_REMOVAL             ,
    fOnVOLUME_CHANGE             ,
    fOnVOLUME_CHANGE_SIZE        ,
    fOnVOLUME_DISMOUNT           ,
    fOnVOLUME_DISMOUNT_FAILED    ,
    fOnVOLUME_FVE_STATUS_CHANGE  ,
    fOnVOLUME_LOCK               ,
    fOnVOLUME_LOCK_FAILED        ,
    fOnVOLUME_MOUNT              ,
    fOnVOLUME_NAME_CHANGE        ,
    fOnVOLUME_NEED_CHKDSK        ,
    fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE ,
    fOnVOLUME_PREPARING_EJECT    ,
    fOnVOLUME_UNIQUE_ID_CHANGE   ,
    fOnVOLUME_UNLOCK             ,
    fOnVOLUME_WEARING_OUT        : TNotifyEvent;

    procedure WndProc(var Message: TMessage);
    procedure Log(AStr: string);
  public
    constructor Create;
    destructor Destroy; override;
    function RegisterThis: Boolean;
    property Logger: TMemo read fLogger write fLogger;
  published
    property OnCDROM_EXCLUSIVE_LOCK      : TNotifyEvent read fOnCDROM_EXCLUSIVE_LOCK     write fOnCDROM_EXCLUSIVE_LOCK     ;
    property OnCDROM_EXCLUSIVE_UNLOCK    : TNotifyEvent read fOnCDROM_EXCLUSIVE_UNLOCK   write fOnCDROM_EXCLUSIVE_UNLOCK   ;
    property OnDEVICE_BECOMING_READY     : TNotifyEvent read fOnDEVICE_BECOMING_READY    write fOnDEVICE_BECOMING_READY    ;
    property OnDEVICE_EXTERNAL_REQUEST   : TNotifyEvent read fOnDEVICE_EXTERNAL_REQUEST  write fOnDEVICE_EXTERNAL_REQUEST  ;
    property OnMEDIA_ARRIVAL             : TNotifyEvent read fOnMEDIA_ARRIVAL            write fOnMEDIA_ARRIVAL            ;
    property OnMEDIA_EJECT_REQUEST       : TNotifyEvent read fOnMEDIA_EJECT_REQUEST      write fOnMEDIA_EJECT_REQUEST      ;
    property OnMEDIA_REMOVAL             : TNotifyEvent read fOnMEDIA_REMOVAL            write fOnMEDIA_REMOVAL            ;
    property OnVOLUME_CHANGE             : TNotifyEvent read fOnVOLUME_CHANGE            write fOnVOLUME_CHANGE            ;
    property OnVOLUME_CHANGE_SIZE        : TNotifyEvent read fOnVOLUME_CHANGE_SIZE       write fOnVOLUME_CHANGE_SIZE       ;
    property OnVOLUME_DISMOUNT           : TNotifyEvent read fOnVOLUME_DISMOUNT          write fOnVOLUME_DISMOUNT          ;
    property OnVOLUME_DISMOUNT_FAILED    : TNotifyEvent read fOnVOLUME_DISMOUNT_FAILED   write fOnVOLUME_DISMOUNT_FAILED   ;
    property OnVOLUME_FVE_STATUS_CHANGE  : TNotifyEvent read fOnVOLUME_FVE_STATUS_CHANGE write fOnVOLUME_FVE_STATUS_CHANGE ;
    property OnVOLUME_LOCK               : TNotifyEvent read fOnVOLUME_LOCK              write fOnVOLUME_LOCK              ;
    property OnVOLUME_LOCK_FAILED        : TNotifyEvent read fOnVOLUME_LOCK_FAILED       write fOnVOLUME_LOCK_FAILED       ;
    property OnVOLUME_MOUNT              : TNotifyEvent read fOnVOLUME_MOUNT             write fOnVOLUME_MOUNT             ;
    property OnVOLUME_NAME_CHANGE        : TNotifyEvent read fOnVOLUME_NAME_CHANGE       write fOnVOLUME_NAME_CHANGE       ;
    property OnVOLUME_NEED_CHKDSK        : TNotifyEvent read fOnVOLUME_NEED_CHKDSK       write fOnVOLUME_NEED_CHKDSK       ;
    property OnVOLUME_PHYSICAL_CONFIGURATION_CHANGE : TNotifyEvent read fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE write fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE;
    property OnVOLUME_PREPARING_EJECT    : TNotifyEvent read fOnVOLUME_PREPARING_EJECT   write fOnVOLUME_PREPARING_EJECT   ;
    property OnVOLUME_UNIQUE_ID_CHANGE   : TNotifyEvent read fOnVOLUME_UNIQUE_ID_CHANGE  write fOnVOLUME_UNIQUE_ID_CHANGE  ;
    property OnVOLUME_UNLOCK             : TNotifyEvent read fOnVOLUME_UNLOCK            write fOnVOLUME_UNLOCK            ;
    property OnVOLUME_WEARING_OUT        : TNotifyEvent read fOnVOLUME_WEARING_OUT       write fOnVOLUME_WEARING_OUT       ;
  end;

  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
  end;

var
  Form1: TForm1;
  dd: TDeviceDetector;

implementation

{$R *.dfm}

type
  PDevBroadcastHdr  = ^DEV_BROADCAST_HDR;
  DEV_BROADCAST_HDR = packed record
    dbch_size       : DWORD;
    dbch_devicetype : DWORD;
    dbch_reserved   : DWORD;
  end;

  PDevBroadcastHandle = ^DEV_BROADCAST_HANDLE;
  DEV_BROADCAST_HANDLE = record
    dbch_size       : DWORD;
    dbch_devicetype : DWORD;
    dbch_reserved   : DWORD;
    dbch_handle     : THandle;
    dbch_hdevnotify : HDEVNOTIFY;
    dbch_eventguid  : TGUID;
    dbch_nameoffset : LONG;
    dbch_data: array [0..0] of Byte;
  end;

const
  DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = $00000004;

  DBT_CUSTOMEVENT = $8006;
  DBT_DEVTYP_HANDLE = $0006;

  GUID_IO_CDROM_EXCLUSIVE_LOCK      : TGUID = '{bc56c139-7a10-47ee-a294-4c6a38f0149a}';
  GUID_IO_CDROM_EXCLUSIVE_UNLOCK    : TGUID = '{a3b6d27d-5e35-4885-81e5-ee18c00ed779}';
  GUID_IO_DEVICE_BECOMING_READY     : TGUID = '{d07433f0-a98e-11d2-917a-00a0c9068ff3}';
  GUID_IO_DEVICE_EXTERNAL_REQUEST   : TGUID = '{d07433d0-a98e-11d2-917a-00a0c9068ff3}';
  GUID_IO_MEDIA_ARRIVAL             : TGUID = '{d07433c0-a98e-11d2-917a-00a0c9068ff3}';
  GUID_IO_MEDIA_EJECT_REQUEST       : TGUID = '{d07433d1-a98e-11d2-917a-00a0c9068ff3}';
  GUID_IO_MEDIA_REMOVAL             : TGUID = '{d07433c1-a98e-11d2-917a-00a0c9068ff3}';
  GUID_IO_VOLUME_CHANGE             : TGUID = '{7373654a-812a-11d0-bec7-08002be2092f}';
  GUID_IO_VOLUME_CHANGE_SIZE        : TGUID = '{3a1625be-ad03-49f1-8ef8-6bbac182d1fd}';
  GUID_IO_VOLUME_DISMOUNT           : TGUID = '{d16a55e8-1059-11d2-8ffd-00a0c9a06d32}';
  GUID_IO_VOLUME_DISMOUNT_FAILED    : TGUID = '{E3C5B178-105D-11D2-8FFD-00A0C9A06D32}';
  GUID_IO_VOLUME_FVE_STATUS_CHANGE  : TGUID = '{062998b2-ee1f-4b6a-b857-e76cbbe9a6da}';
  GUID_IO_VOLUME_LOCK               : TGUID = '{50708874-c9af-11d1-8fef-00a0c9a06d32}';
  GUID_IO_VOLUME_LOCK_FAILED        : TGUID = '{ae2eed10-0ba8-11d2-8ffb-00a0c9a06d32}';
  GUID_IO_VOLUME_MOUNT              : TGUID = '{b5804878-1a96-11d2-8ffd-00a0c9a06d32}';
  GUID_IO_VOLUME_NAME_CHANGE        : TGUID = '{2de97f83-4c06-11d2-a532-00609713055a}';
  GUID_IO_VOLUME_NEED_CHKDSK        : TGUID = '{799a0960-0a0b-4e03-ad88-2fa7c6ce748a}';
  GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE : TGUID = '{2de97f84-4c06-11d2-a532-00609713055a}';
  GUID_IO_VOLUME_PREPARING_EJECT    : TGUID = '{c79eb16e-0dac-4e7a-a86c-b25ceeaa88f6}';
  GUID_IO_VOLUME_UNIQUE_ID_CHANGE   : TGUID = '{af39da42-6622-41f5-970b-139d092fa3d9}';
  GUID_IO_VOLUME_UNLOCK             : TGUID = '{9a8c3d68-d0cb-11d1-8fef-00a0c9a06d32}';
  GUID_IO_VOLUME_WEARING_OUT        : TGUID = '{873113ca-1486-4508-82ac-c3b2e5297aaa}';




function WDE_GUID_To_String(AGUID: TGUID): string; //WDE stands for Windows Device Events
begin
  if AGUID = GUID_IO_CDROM_EXCLUSIVE_LOCK     then result := 'GUID_IO_CDROM_EXCLUSIVE_LOCK'     else
  if AGUID = GUID_IO_CDROM_EXCLUSIVE_UNLOCK   then result := 'GUID_IO_CDROM_EXCLUSIVE_UNLOCK'   else
  if AGUID = GUID_IO_DEVICE_BECOMING_READY    then result := 'GUID_IO_DEVICE_BECOMING_READY'    else
  if AGUID = GUID_IO_DEVICE_EXTERNAL_REQUEST  then result := 'GUID_IO_DEVICE_BECOMING_READY'    else
  if AGUID = GUID_IO_MEDIA_ARRIVAL            then result := 'GUID_IO_MEDIA_ARRIVAL'            else
  if AGUID = GUID_IO_MEDIA_EJECT_REQUEST      then result := 'GUID_IO_MEDIA_EJECT_REQUEST'      else
  if AGUID = GUID_IO_MEDIA_REMOVAL            then result := 'GUID_IO_MEDIA_REMOVAL'            else
  if AGUID = GUID_IO_VOLUME_CHANGE            then result := 'GUID_IO_VOLUME_CHANGE'            else
  if AGUID = GUID_IO_VOLUME_CHANGE_SIZE       then result := 'GUID_IO_VOLUME_CHANGE_SIZE'       else
  if AGUID = GUID_IO_VOLUME_DISMOUNT          then result := 'GUID_IO_VOLUME_DISMOUNT'          else
  if AGUID = GUID_IO_VOLUME_DISMOUNT_FAILED   then result := 'GUID_IO_VOLUME_DISMOUNT_FAILED'   else
  if AGUID = GUID_IO_VOLUME_FVE_STATUS_CHANGE then result := 'GUID_IO_VOLUME_FVE_STATUS_CHANGE' else
  if AGUID = GUID_IO_VOLUME_LOCK              then result := 'GUID_IO_VOLUME_LOCK'              else
  if AGUID = GUID_IO_VOLUME_LOCK_FAILED       then result := 'GUID_IO_VOLUME_LOCK_FAILED'       else
  if AGUID = GUID_IO_VOLUME_MOUNT             then result := 'GUID_IO_VOLUME_MOUNT'             else
  if AGUID = GUID_IO_VOLUME_NAME_CHANGE       then result := 'GUID_IO_VOLUME_NAME_CHANGE'       else
  if AGUID = GUID_IO_VOLUME_NEED_CHKDSK       then result := 'GUID_IO_VOLUME_NEED_CHKDSK'       else

  if AGUID = GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE then result := 'GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE' else

  if AGUID = GUID_IO_VOLUME_PREPARING_EJECT   then result := 'GUID_IO_VOLUME_PREPARING_EJECT'   else
  if AGUID = GUID_IO_VOLUME_UNIQUE_ID_CHANGE  then result := 'GUID_IO_VOLUME_UNIQUE_ID_CHANGE'  else
  if AGUID = GUID_IO_VOLUME_UNLOCK            then result := 'GUID_IO_VOLUME_UNLOCK'            else
  if AGUID = GUID_IO_VOLUME_WEARING_OUT       then result := 'GUID_IO_VOLUME_WEARING_OUT';
end;



constructor TDeviceDetector.Create;
begin
  inherited;
  fHandle := AllocateHWnd(WndProc);
end;

destructor TDeviceDetector.Destroy;
begin
  DeallocateHWnd(fHandle);
  inherited;
end;

function TDeviceDetector.RegisterThis: Boolean;
var
  dbv: DEV_BROADCAST_HANDLE;
  Size: Integer;
  r: Pointer;
begin
  Size := SizeOf(DEV_BROADCAST_HANDLE);
  ZeroMemory(@dbv, Size);
  dbv.dbch_size := Size;
  dbv.dbch_devicetype := DBT_DEVTYP_HANDLE;
  dbv.dbch_reserved := 0;
  dbv.dbch_handle  := CreateFileA('\\.\E:', GENERIC_READ, FILE_SHARE_READ + FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING + FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0);
  dbv.dbch_hdevnotify := RegisterDeviceNotification(fHandle, @dbv, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);;
  dbv.dbch_nameoffset := 0;


  if Assigned(dbv.dbch_hdevnotify) then Result := True;
end;

procedure TDeviceDetector.WndProc(var Message: TMessage);
  var data: PDevBroadcastHdr;
      data_H: PDevBroadcastHandle;
begin
  if Message.wParam = DBT_CUSTOMEVENT then  //according to MSDN, DEV_BROADCAST_HANDLE structure is treated as a custom event.
  begin
    Data := PDevBroadcastHdr(Message.LParam); //we need to treat this custom evend a DEV_BROADCAST_HDR structure first...

    if Data^.dbch_devicetype = DBT_DEVTYP_HANDLE then //then we check if the device type is DBT_DEVTYP_HANDLE
    begin
      data_H := PDevBroadcastHandle(Message.lParam); //if the device type is DBT_DEVTYP_HANDLE, we treat the custom event as a DEV_BROADCAST_HANDLE structure

      //final step is to see what GUID the event of the structure DEV_BROADCAST_HANDLE has

      Log(WDE_GUID_To_String(data_H^.dbch_eventguid));

      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_CDROM_EXCLUSIVE_LOCK)      = true then if assigned(fOnCDROM_EXCLUSIVE_LOCK)      then fOnCDROM_EXCLUSIVE_LOCK(self)      else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_CDROM_EXCLUSIVE_UNLOCK)    = true then if assigned(fOnCDROM_EXCLUSIVE_UNLOCK)    then fOnCDROM_EXCLUSIVE_UNLOCK(self)    else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_DEVICE_BECOMING_READY)     = true then if assigned(fOnDEVICE_BECOMING_READY)     then fOnDEVICE_BECOMING_READY(self)     else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_DEVICE_EXTERNAL_REQUEST)   = true then if assigned(fOnDEVICE_EXTERNAL_REQUEST)   then fOnDEVICE_EXTERNAL_REQUEST(self)   else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_MEDIA_ARRIVAL)             = true then if assigned(fOnMEDIA_ARRIVAL)             then fOnMEDIA_ARRIVAL(self)             else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_MEDIA_EJECT_REQUEST)       = true then if assigned(fOnMEDIA_EJECT_REQUEST)       then fOnMEDIA_EJECT_REQUEST(self)       else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_MEDIA_REMOVAL)             = true then if assigned(fOnMEDIA_REMOVAL)             then fOnMEDIA_REMOVAL(self)             else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_CHANGE)             = true then if assigned(fOnVOLUME_CHANGE)             then fOnVOLUME_CHANGE(self)             else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_CHANGE_SIZE)        = true then if assigned(fOnVOLUME_CHANGE_SIZE)        then fOnVOLUME_CHANGE_SIZE(self)        else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_DISMOUNT)           = true then if assigned(fOnVOLUME_DISMOUNT)           then fOnVOLUME_DISMOUNT(self)           else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_DISMOUNT_FAILED)    = true then if assigned(fOnVOLUME_DISMOUNT_FAILED)    then fOnVOLUME_DISMOUNT_FAILED(self)    else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_FVE_STATUS_CHANGE)  = true then if assigned(fOnVOLUME_FVE_STATUS_CHANGE)  then fOnVOLUME_FVE_STATUS_CHANGE(self)  else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_LOCK)               = true then if assigned(fOnVOLUME_LOCK)               then fOnVOLUME_LOCK(self)               else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_LOCK_FAILED)        = true then if assigned(fOnVOLUME_LOCK_FAILED)        then fOnVOLUME_LOCK_FAILED(self)        else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_MOUNT)              = true then if assigned(fOnVOLUME_MOUNT)              then fOnVOLUME_MOUNT(self)              else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_NAME_CHANGE)        = true then if assigned(fOnVOLUME_NAME_CHANGE)        then fOnVOLUME_NAME_CHANGE(self)        else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_NEED_CHKDSK)        = true then if assigned(fOnVOLUME_NEED_CHKDSK)        then fOnVOLUME_NEED_CHKDSK(self)        else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE) = true then if assigned(fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE) then fOnVOLUME_PHYSICAL_CONFIGURATION_CHANGE(self) else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_PREPARING_EJECT)    = true then if assigned(fOnVOLUME_PREPARING_EJECT)    then fOnVOLUME_PREPARING_EJECT(self)    else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_UNIQUE_ID_CHANGE)   = true then if assigned(fOnVOLUME_UNIQUE_ID_CHANGE)   then fOnVOLUME_UNIQUE_ID_CHANGE(self)   else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_UNLOCK)             = true then if assigned(fOnVOLUME_UNLOCK)             then fOnVOLUME_UNLOCK(self)             else
      if IsEqualGUID(data_H^.dbch_eventguid, GUID_IO_VOLUME_WEARING_OUT)        = true then if assigned(fOnVOLUME_WEARING_OUT)        then fOnVOLUME_WEARING_OUT(self);
    end;

  end;
end;

procedure TDeviceDetector.Log(AStr: string);
begin
  fLogger.Lines.Add(AStr);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  dd := TDeviceDetector.Create;
  dd.Logger := Memo1;
  if dd.RegisterThis = true then Memo1.Lines.Add('Registered!') else Memo1.Lines.Add('Failed to register!');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  dd.free;
end;


end.

这篇关于使用Delphi检测在Windows中安装卷的时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆