Как распознавать подсоединение флэшки?
Модератор: Модераторы
Как распознавать подсоединение флэшки?
Всем привет,
подскажите как распознавать подсоединение флэшки или когда ее извлекают? То есть сам процесс как найти флэшку я знаю, я ищу только тот момент когда флэшку втыкают и извлекают. Сейчас я "сканирую" все диски таймером и так узнаю, добавилось что то или убавилось. Но это как то не профессионально.
Как получать инфу от Windows о том подключили флэш-устроиство или извлекли?
Пасиб!
подскажите как распознавать подсоединение флэшки или когда ее извлекают? То есть сам процесс как найти флэшку я знаю, я ищу только тот момент когда флэшку втыкают и извлекают. Сейчас я "сканирую" все диски таймером и так узнаю, добавилось что то или убавилось. Но это как то не профессионально.
Как получать инфу от Windows о том подключили флэш-устроиство или извлекли?
Пасиб!
Нашел вот этот код, но не пойму как добавить, что бы узнавались и SD-Card? Кто может подсказать?
Код: Выделить всё
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
Windows;
type
{ TForm1 }
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
const
GUID_DEVINTERFACE_USB_DEVICE: TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';
var
Form1: TForm1;
implementation
uses JwaWinUser, JwaDbt;
{$R *.lfm}
type
TMWndProc = Windows.WNDPROC;
var
OldWndProc : TMWndProc;
function MyWndProc(my_wnd : HWND; Msg : UINT;
my_wparam : WPARAM; my_lparam : LPARAM) : LRESULT; stdcall;
var
devType : Integer;
Datos : PDevBroadcastHdr;
begin
Result := 0;
case Msg of
WM_DEVICECHANGE:
begin
if (my_wparam = DBT_DEVICEARRIVAL) or (my_wparam = DBT_DEVICEREMOVECOMPLETE) then
begin
Datos := PDevBroadcastHdr(Pointer(my_lparam));
devType := Datos^.dbch_devicetype;
if devType = DBT_DEVTYP_DEVICEINTERFACE then
begin
if my_wparam = DBT_DEVICEARRIVAL then
ShowMessage('USB устройство подключено')
else
ShowMessage('USB устройство отключено');
end;
end;
// Здесь нужно, если не ошибаюсь, вернуть результат:
// Return TRUE to grant the request
// Return BROADCAST_QUERY_DENY to deny the request.
end; // WM_DEVICECHANGE
end; // case
Result := Windows.CallWindowProc(OldWndProc, my_wnd, Msg, my_wparam, my_lparam);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
dbi: DEV_BROADCAST_DEVICEINTERFACE_W;
Size: Integer;
RDN: HDEVNOTIFY;
arr : array[0 .. 0] of word;
begin
arr[0] := 0;
Size := SizeOf(DEV_BROADCAST_DEVICEINTERFACE_W);
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 := arr;
RDN := RegisterDeviceNotificationW(Form1.Handle, @dbi,
DEVICE_NOTIFY_WINDOW_HANDLE);
if not Assigned(RDN) then
begin
ShowMessage('Error Register Message');
end;
OldWndProc := TMWndProc(Windows.GetWindowLong(Self.Handle, GWL_WNDPROC));
Windows.SetWindowLong(Self.Handle, GWL_WNDPROC, LongInt(@MyWndProc));
end;
end.
Ещё надо добавить
TDEV_BROADCAST_VOLUME
TDEV_BROADCAST_VOLUME
Код: Выделить всё
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;
{ Private declarations }
public
{ Public declarations }
end;
PDevBroadcastHdr = ^DEV_BROADCAST_HDR;
DEV_BROADCAST_HDR = packed record
dbch_size: DWORD;
dbch_devicetype: DWORD;
dbch_reserved: DWORD;
end;
PTDEV_BROADCAST_DEVICEINTERFACE = ^TDEV_BROADCAST_DEVICEINTERFACE;
TDEV_BROADCAST_DEVICEINTERFACE = record
dbcc_size: DWORD;
dbcc_devicetype: DWORD;
dbcc_reserved: DWORD;
dbcc_classguid: TGUID;
dbcc_name: short;
end;
PDEV_BROADCAST_VOLUME=^TDEV_BROADCAST_VOLUME;
TDEV_BROADCAST_VOLUME= record
dbcv_size: DWORD;
dbcv_devicetype: DWORD;
dbcv_reserved: DWORD;
dbcv_unitmask:DWord;
dbcv_flags:Word;
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
DBT_DEVTYP_VOLUME = $00000002;
var
Form1: TForm1;
QarantinDir:String='c:\Qarantin\';
implementation
{$R *.dfm}
procedure LogAdd(Text:String);
begin
end;
procedure ToQarantin(FullFileName:String);
var
Path,FileName:String;
begin
Zip(Path+FileName,QarantinDir+FileName);
LogAdd('File copy to Qarantin:'''+FileName+'''');
end;
procedure DeleteFile(FileName:String);
begin
if DeleteFile(FileName) then
begin
LogAdd('File deleted:'''+FileName+'''');
end else
begin
LogAdd('File not deleted:'''+FileName+'''');
end;
end;
procedure DetectAutorun(Volume:string);
var
SearchRec : TSearchRec;
FileDesc:PFileDesc;
Mask:String;
begin
Mask:='Autorun.inf'
if FindFirst(Volume+Mask, faAnyFile, SearchRec) = 0 then
begin
IF (SearchRec.Attr and faDirectory) <> faDirectory then
begin
ToQarantin(Volume,Mask);
DeleteFile(Volume+Mask);
end;
end;
end;
procedure DetectVirusOnFlash(volume:String);
begin
DetectAutorun(Volume);
end;
procedure DetectFlash;
var
drive:string;
t:UInt;
p:PChar;
i,Len:Integer;
begin
p:=nil;
Len:=GetLogicalDriveStrings(0,p);
GetMem(p,Len+1);
Len:=GetLogicalDriveStrings(Len,p);
drive:='';
for i := 0 to Len-1 do // Определяем букву устройства
begin
if p[i]<>#0 then
begin
drive:=drive+p[i];
end
else
begin
t:=GetDriveType(PChar(drive));
if t=DRIVE_REMOVABLE then //Проверяем тип устройства
// Если это флешка, то...
begin
DetectVirusOnFlash(drive);
//showmessage('Была воткнута Флешка');
//....
end;
drive:='';
end;
end;
FreeMem(p);
end;
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_VOLUME then
begin // USB Device
if Msg.wParam = DBT_DEVICEARRIVAL then
begin
DetectFlash;
//showmessage('Устройство подключено'); // Усройство подключено
//.....
end
else
begin
//showmessage('Устройство ОТКЛЮЧЕНО');
//.....
end;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
dbi: TDEV_BROADCAST_DEVICEINTERFACE;
dbv: TDEV_BROADCAST_VOLUME;
Size: Integer;
r: Pointer;
begin
Size := SizeOf(TDEV_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');
Size := SizeOf(TDEV_BROADCAST_VOLUME);
ZeroMemory(@dbv, Size);
dbv.dbcv_size := Size;
dbv.dbcv_devicetype := DBT_DEVTYP_VOLUME;
dbv.dbcv_reserved := 0;
dbv.dbcv_flags := 0;
r := RegisterDeviceNotification(Form1.Handle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE);
if not Assigned(r) then
ShowMessage('Error Register Message');
end;
end.А зачем это добавлять? Это пример под Lazarus или Delphi?
У функции GetDriveType для флешки и флеш-карты разные константы возвращаются, может у тебя тоже все дело в том что ты получаешь оповещение о целом устройстве, а не съемном носителе для устройства.
Я GetDriveType не использую...
McLion писал(а):Я GetDriveType не использую...
Ты увидел слово GetDriveType , а надо было
для флешки и флеш-карты разные константы возвращаются
Выше Pavia привел пример. У тебя в FormCreate регистрируется одно оповещение, как я вижу, а у него в коде в том же FormCreate регистрируется два оповещения, для двух типов носителей.
А что если просто поменять на ??? После того как TDEV_BROADCAST_VOLUME добавить? Вроде работает, и флеш-карты узнает!
Добавлено спустя 12 часов 43 минуты 36 секунд:
По моему у тебя ошибка в коде, @dbi нужно на @dbv поменять, во второй функции RegisterDeviceNotification.
Код: Выделить всё
if devType = DBT_DEVTYP_DEVICEINTERFACE thenКод: Выделить всё
if devType = DBT_DEVTYP_VOLUME thenДобавлено спустя 12 часов 43 минуты 36 секунд:
Pavia писал(а):Ещё надо добавить
TDEV_BROADCAST_VOLUME
По моему у тебя ошибка в коде, @dbi нужно на @dbv поменять, во второй функции RegisterDeviceNotification.
Код: Выделить всё
r := RegisterDeviceNotification(Form1.Handle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE);Код: Выделить всё
r := RegisterDeviceNotification(Self.Handle, @dbv, DEVICE_NOTIFY_WINDOW_HANDLE);Не в первый раз наблюдаю, что интерес к одной и той же теме возникает сразу в нескольких местах.
Это потому что все на одних и тех же фрилансах сайтах работают?
Это потому что все на одних и тех же фрилансах сайтах работают?
Код из черновика. Особо не гонял
Да.
Сообщения надо зарегистрировать на прием. Иначе форма их вообще не будет получать.
Но учти разные карт-ридеры работают по разному. Кто-то генерирует оба сообщения, а кто-то только одно.
И плюс CD-карты и флешки могут быть не отформатированными. И скорее всего они не будут генерировать VOLUME.
McLion писал(а):По моему у тебя ошибка в коде, @dbi нужно на @dbv поменять, во второй функции RegisterDeviceNotification.
Да.
Сообщения надо зарегистрировать на прием. Иначе форма их вообще не будет получать.
Но учти разные карт-ридеры работают по разному. Кто-то генерирует оба сообщения, а кто-то только одно.
И плюс CD-карты и флешки могут быть не отформатированными. И скорее всего они не будут генерировать VOLUME.
Я так посмотрел на весь этот винегрет и подумал, что буду сканировать таймером все диски и таким образом всегда буду знать, что добавилось или отнялось. Как то проще все будет, хоть и не совсем элегантно.
