Как распознавать подсоединение флэшки?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Как распознавать подсоединение флэшки?

Сообщение McLion » 27.06.2015 15:25:47

Всем привет,

подскажите как распознавать подсоединение флэшки или когда ее извлекают? То есть сам процесс как найти флэшку я знаю, я ищу только тот момент когда флэшку втыкают и извлекают. Сейчас я "сканирую" все диски таймером и так узнаю, добавилось что то или убавилось. Но это как то не профессионально.

Как получать инфу от Windows о том подключили флэш-устроиство или извлекли?

Пасиб!
Аватара пользователя
McLion
постоялец
 
Сообщения: 332
Зарегистрирован: 06.02.2015 18:41:00

Re: Как распознавать подсоединение флэшки?

Сообщение скалогрыз » 27.06.2015 18:06:49

скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Как распознавать подсоединение флэшки?

Сообщение McLion » 30.06.2015 21:21:42

Нашел вот этот код, но не пойму как добавить, что бы узнавались и 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.
Аватара пользователя
McLion
постоялец
 
Сообщения: 332
Зарегистрирован: 06.02.2015 18:41:00

Re: Как распознавать подсоединение флэшки?

Сообщение Pavia » 30.06.2015 22:08:24

Ещё надо добавить
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.
Аватара пользователя
Pavia
постоялец
 
Сообщения: 290
Зарегистрирован: 07.01.2011 12:46:51

Re: Как распознавать подсоединение флэшки?

Сообщение McLion » 30.06.2015 22:35:45

А зачем это добавлять? Это пример под Lazarus или Delphi?
Аватара пользователя
McLion
постоялец
 
Сообщения: 332
Зарегистрирован: 06.02.2015 18:41:00

Re: Как распознавать подсоединение флэшки?

Сообщение Sharfik » 30.06.2015 22:40:25

У функции GetDriveType для флешки и флеш-карты разные константы возвращаются, может у тебя тоже все дело в том что ты получаешь оповещение о целом устройстве, а не съемном носителе для устройства.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 809
Зарегистрирован: 20.07.2013 01:04:30

Re: Как распознавать подсоединение флэшки?

Сообщение McLion » 30.06.2015 22:43:13

Я GetDriveType не использую...
Аватара пользователя
McLion
постоялец
 
Сообщения: 332
Зарегистрирован: 06.02.2015 18:41:00

Re: Как распознавать подсоединение флэшки?

Сообщение Sharfik » 30.06.2015 22:55:28

McLion писал(а):Я GetDriveType не использую...

Ты увидел слово GetDriveType , а надо было
для флешки и флеш-карты разные константы возвращаются


Выше Pavia привел пример. У тебя в FormCreate регистрируется одно оповещение, как я вижу, а у него в коде в том же FormCreate регистрируется два оповещения, для двух типов носителей.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 809
Зарегистрирован: 20.07.2013 01:04:30

Re: Как распознавать подсоединение флэшки?

Сообщение McLion » 30.06.2015 23:07:53

А что если просто
Код: Выделить всё
if devType = DBT_DEVTYP_DEVICEINTERFACE then
поменять на
Код: Выделить всё
if devType = DBT_DEVTYP_VOLUME then
??? После того как TDEV_BROADCAST_VOLUME добавить? Вроде работает, и флеш-карты узнает!

Добавлено спустя 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);
Аватара пользователя
McLion
постоялец
 
Сообщения: 332
Зарегистрирован: 06.02.2015 18:41:00

Re: Как распознавать подсоединение флэшки?

Сообщение скалогрыз » 01.07.2015 15:49:17

Не в первый раз наблюдаю, что интерес к одной и той же теме возникает сразу в нескольких местах.
Это потому что все на одних и тех же фрилансах сайтах работают?
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Как распознавать подсоединение флэшки?

Сообщение Pavia » 01.07.2015 17:13:06

Код из черновика. Особо не гонял
McLion писал(а):По моему у тебя ошибка в коде, @dbi нужно на @dbv поменять, во второй функции RegisterDeviceNotification.

Да.
Сообщения надо зарегистрировать на прием. Иначе форма их вообще не будет получать.
Но учти разные карт-ридеры работают по разному. Кто-то генерирует оба сообщения, а кто-то только одно.
И плюс CD-карты и флешки могут быть не отформатированными. И скорее всего они не будут генерировать VOLUME.
Аватара пользователя
Pavia
постоялец
 
Сообщения: 290
Зарегистрирован: 07.01.2011 12:46:51

Re: Как распознавать подсоединение флэшки?

Сообщение McLion » 01.07.2015 23:28:18

Я так посмотрел на весь этот винегрет и подумал, что буду сканировать таймером все диски и таким образом всегда буду знать, что добавилось или отнялось. Как то проще все будет, хоть и не совсем элегантно.
Аватара пользователя
McLion
постоялец
 
Сообщения: 332
Зарегистрирован: 06.02.2015 18:41:00


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 218

Рейтинг@Mail.ru