Консультация № 176483
04.02.2010, 12:59
43.65 руб.
0 12 1
Здравствуйте уважаемые!
Стоит такая задача: нужно определить момент подключения флэшки (любой) к компьютеру и послать сообщение администратору. Меня интересует именно сам момент подключения - как его отловить?

Обсуждение

давно
Профессионал
153662
1070
04.02.2010, 13:13
общий
sir Henry:
На сайте forum.sources.ru встречал такой пост
Это когда-то пробовали поймать подключение усб модема. Это функция, принимает события WM_DEVICECHANGE которое приходит, в то время когда подключаешь усб. Может поможет.
Код:
void __fastcall TMainFrame::WndProc(Messages::TMessage &Message)
{
if (Message.Msg == WM_DEVICECHANGE && Message.WParam == DBT_DEVICEARRIVAL)
{
ResetEvent(eDeviceEvent);
DEV_BROADCAST_HDR *header = (DEV_BROADCAST_HDR *) Message.LParam;
if (header->dbch_devicetype == DBT_DEVTYP_PORT)
{
DEV_BROADCAST_PORT *port = (DEV_BROADCAST_PORT *) Message.LParam;
char wndInfo[512];
sprintf(wndInfo, "Window received WM_DEVICECHANGE(DBT_DEVICEARRIVAL) message\r\n\tPort "%s" connected", port->dbcp_name);
pModemComm->AddToMemo(AnsiString(wndInfo));
//WriteFile(hLogfile, wndInfo, iStored, &bytesWritten, NULL);
//SendMessage(GlobalData->AppHandle, WM_COPYDATA, 0, (LPARAM)wndInfo);
hThreadReenum = CreateThread( NULL, 0, TMainFrame::ThreadEnumerate, (LPVOID)this, 0, &dwThreadId );
} // if (header->dbch_devicetype == DBT_DEVTYP_PORT)
}
//TControl::WndProc(Message);
TForm::WndProc(Message);
}
А вот описание WM_DEVICECHANGE.
Вот из ДРКБ Может быть, чем-то поможет.
Detect if a USB device is connected or disconnected?
Код:
unit U_Usb;
interface

uses
Windows, Messages, SysUtils, Classes, 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;

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 class

type
TComponentUSB = class(TComponent)
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(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnUSBArrival: TNotifyEvent read FOnUSBArrival write FOnUSBArrival;
property OnUSBRemove: TNotifyEvent read FOnUSBRemove write FOnUSBRemove;
end;

implementation

constructor TComponentUSB.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWindowHandle := AllocateHWnd(WndProc);
USBRegister;
end;

destructor TComponentUSB.Destroy;
begin
DeallocateHWnd(FWindowHandle);
inherited Destroy;
end;

procedure TComponentUSB.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;

procedure TComponentUSB.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;

function TComponentUSB.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;

end.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Мастер-Эксперт
425
4118
04.02.2010, 13:58
общий
Евгений/Genia007/:
Большое спасибо, сейчас попробую.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Профессионал
153662
1070
04.02.2010, 13:59
общий
А вот ещё
Код:
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;

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 class

//...

private
procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;

//...

implementation

procedure TForm1.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
// Усройство подключено
end
else
begin
// Усройство отключено
end;
end;
end;
end;

procedure TForm1.OnCreate({...}); //!!!!!!!!!!!!!
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(Form1.Handle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE);
if not Assigned(r) then
ShowMessage('Error Register Message')
end;
Отзыв положительный.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Мастер-Эксперт
425
4118
04.02.2010, 14:23
общий
Евгений/Genia007/:
В принципе вопрос можно закрывать - нашёл оригинальный и очень махонький сишный исходник. Вот его переделка на Паскаль:
Код:
Uses windows;

var
MSG: Tmsg;
Begin
CreateWindow('Hidden', NIL,0,0,0,0,0,0,0,0,NIL);

while GetMessage(msg,0,0,0) Do
if msg.message=WM_DEVICECHANGE Then
MessageBox(0,'Уряяя !!! =))', '', MB_OK);

End.


Вам спасибо за подсказку, она мне очень помогла.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Мастер-Эксперт
425
4118
04.02.2010, 14:28
общий
Евгений/Genia007/:
Перенесите своё сообщение из мини-форума в ответы, чтобы Вам деньги за ответ поступили.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Профессионал
153662
1070
04.02.2010, 14:39
общий
sir Henry:
А какое перенести из трёх?
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Мастер-Эксперт
425
4118
04.02.2010, 14:44
общий
Евгений/Genia007/:
На мысль меня натолкнул самый первый, но можете все три, так даже лучше.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Профессионал
153662
1070
04.02.2010, 14:54
общий
это ответ
Здравствуйте, sir Henry.
Для этого нужно обрабатывать событие WM_DEVICECHANGE которое приходит, в то время когда подключаешь usb.
Здесь можно посмотреть описание WM_DEVICECHANGE. А вот несколько примеров из интернета:
Код:
сайт forum.sources.ru, borland c++
void __fastcall TMainFrame::WndProc(Messages::TMessage &Message)
{
if (Message.Msg == WM_DEVICECHANGE && Message.WParam == DBT_DEVICEARRIVAL)
{
ResetEvent(eDeviceEvent);
DEV_BROADCAST_HDR *header = (DEV_BROADCAST_HDR *) Message.LParam;
if (header->dbch_devicetype == DBT_DEVTYP_PORT)
{
DEV_BROADCAST_PORT *port = (DEV_BROADCAST_PORT *) Message.LParam;
char wndInfo[512];
sprintf(wndInfo, "Window received WM_DEVICECHANGE(DBT_DEVICEARRIVAL) message\r\n\tPort "%s" connected", port->dbcp_name);
pModemComm->AddToMemo(AnsiString(wndInfo));
//WriteFile(hLogfile, wndInfo, iStored, &bytesWritten, NULL);
//SendMessage(GlobalData->AppHandle, WM_COPYDATA, 0, (LPARAM)wndInfo);
hThreadReenum = CreateThread( NULL, 0, TMainFrame::ThreadEnumerate, (LPVOID)this, 0, &dwThreadId );
} // if (header->dbch_devicetype == DBT_DEVTYP_PORT)
}
//TControl::WndProc(Message);
TForm::WndProc(Message);
}

Код:
ДРКБ Detect if a USB device is connected or disconnected? 
unit U_Usb;
interface

uses
Windows, Messages, SysUtils, Classes, 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;

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 class

type
TComponentUSB = class(TComponent)
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(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnUSBArrival: TNotifyEvent read FOnUSBArrival write FOnUSBArrival;
property OnUSBRemove: TNotifyEvent read FOnUSBRemove write FOnUSBRemove;
end;

implementation

constructor TComponentUSB.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWindowHandle := AllocateHWnd(WndProc);
USBRegister;
end;

destructor TComponentUSB.Destroy;
begin
DeallocateHWnd(FWindowHandle);
inherited Destroy;
end;

procedure TComponentUSB.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;

procedure TComponentUSB.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;

function TComponentUSB.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;

end.

Код:
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;

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 class

//...

private
procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;

//...

implementation

procedure TForm1.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
// Усройство подключено
end
else
begin
// Усройство отключено
end;
end;
end;
end;

procedure TForm1.OnCreate({...}); //!!!!!!!!!!!!!
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(Form1.Handle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE);
if not Assigned(r) then
ShowMessage('Error Register Message')
end;
5
Большое спасибо! Особенно за WM_DEVICECHANGE. :)
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Мастер-Эксперт
319965
1463
04.02.2010, 18:34
общий
sir Henry:
Еще один пример:
http://www.rsdn.ru/forum/asm/1891895.all.aspx
давно
Мастер-Эксперт
425
4118
04.02.2010, 18:53
общий
star9491:
Спасибо, тоже интересно.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Мастер-Эксперт
259041
7459
06.02.2010, 03:38
общий
Господа программисты, это хорошо, что вы для себя двоих решили проблему фиксации события подключения флэшки. А не могли бы вы помочь широкой публике, незнакомой с прог-языками? Многие посетители и эксперты умеют пользоваться (bat-)cmd-файлами, но cmd-процессор не содержит функции отслеживания событий.
Пожалуйста, опишите: Как с помощью вашего "очень махонький сишный исходник" при подключении флэшки авто-запустить C:\handler.cmd , в котором многие смогут запрограммировать зачитывание реестр-раздела с устройствами и передачу текущ времени и типа устройства в сеть или в лог?
давно
Мастер-Эксперт
425
4118
06.02.2010, 06:42
общий
Алексеев Владимир:
Задайте свой вопрос в соответствующую рассылку.
В мини-форуме обсуждается только текущий вопрос, а не чьи либо проблемы и Вы, как эксперт с высоким статусом, должны это не только знать (прочитав Правила), но и неукоснительно соблюдать.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Форма ответа