Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Работа с флэшкой..


Автор: Grol 20.3.2006, 23:31
В USB втыкаю флэшку (любую), после обнаружения ее Виндой, флэшка станет как съемное устройство и займет какую-то букву латинского алфавита. Необходимо сделать программу, которая висела бы в памяти и обнаруживала подключенные флэшки и определяла какие диски (имя диска) эти съемные устройства занимали бы? Вообще как можно реализовать такую программу. Самое главное, что мне нужно знать это как обнаружить флэшку и имя диска на который флэшка встала....Спасибо заранее за ответы.

Автор: XbiT 20.3.2006, 23:39
посмотри тут:
http://forum.vingrad.ru/index.php?showtopic=84349

Автор: Grol 21.3.2006, 00:03
Спасибо большое, ща попробую разобраться!

Автор: Grol 21.3.2006, 00:56
Думал все просто...а нет! Нашел в тех ссылках, что мне дали такой код:
Код

unit USB_device;

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.

А что с ним делать, ума не приложу. Помогите пожалуйста неопытному программисту...

Автор: Grol 21.3.2006, 02:44
Так что можно сделать? Хоть чуть чуть помогите... smile

Автор: Snowy 21.3.2006, 10:38
Вот тебе волшебный файлик.
Распакуй его в папку Lib и установи, как новый компонент.
Он встанет на закладку 'System'. Брось его на форму и юзай.

Автор: Grol 24.3.2006, 05:33
Большое пребольшое спасибо smile , все работает. А вот такой вопрос, а как можно обнаружить уже подключенные флэшки? Т.е. до загрузки моей программы, которая ловит подключение флэшки, были уже подключены флэш устройства. И моя программа не найдет их, т.к. сообщение WM_DEVICECHANGE действует только при подключении флэшки и ее отключении. smile Конечно извините за 2 вопроса в одной теме, но вроде тематика не нарушается. Буду благодарен за следующие ответы. По окончанию работы скину этот проект сюда...если мне здесь помогут...smile

Автор: Snowy 24.3.2006, 09:58
При старте программы просканируй диски на наличие съемных.
Код
function GetRemovableDrives: string;
var
  d: dword;
  b: byte;
begin
  result := '';
  d := GetLogicalDrives;
  for b := 2 to 26 do
    if 1 shl b and d > 0 then
      if GetDriveType(PChar(chr(b+65)+':\')) = DRIVE_REMOVABLE then
        result := result + chr(b+65);
end;

Правда если попадутся какие-нить ZIP драйвы или USB флопики, то они тоже в список попадут.
Но такая вероятность невелика. Да и не особо существенна.

Автор: Grol 24.3.2006, 23:43
Спасибо вроде бы все сделал, что хотел...вот принимайте smile Только вот один касяк есть...когда прога обнаружила флэшку и я с ней сделал все что хотел, т.е. программа больше ничего не делает с флэш устройством....то после этого всего флэшка не хочет безопасно извлекаться из системы (говорит что типа флэш устройство еще занято), хотя прога больше ничего не делает с ней. Извлечь безопасно флэшку можно только в случае, если я принудительно убью мою прогу. Если кто знает как исправить это, то пожалуйста напишите сюда....
Вот ссылка на проект http://webfile.ru/876803 (там архив Pro.rar - Pass:11111)

Автор: onyxx 4.8.2007, 16:53
А можно последний проект выложить здесь? там уже файла нету...

Автор: bems 4.8.2007, 18:18
Цитата(Grol @  24.3.2006,  23:43 Найти цитируемый пост)
т.е. программа больше ничего не делает с флэш устройством...
а что делает? а хэндлы закрывает?

Автор: MetalFan 4.8.2007, 19:58
onyxx, может тебе еще и ключи от квартиры, где деньги лежат? )))

Автор: diablist 12.12.2007, 12:58
Выкидывает в комбобокс правда вместе с дискетами:

Код

procedure TForm1.drivesDropDown(Sender: TObject);
var
j:cardinal;
begin
drives.Clear;
for j:=ord('A')  to ord('Z') do
    if Getdrivetype(pchar(chr(j)+':\'))=DRIVE_REMOVABLE then
       drives.Items.Add(chr(j));
end;


Пишет в неиспользуемые части флешки:
Код

if drives.Text<>''then
   begin
        f:=createfile(pchar('\\.\'+drives.Text+':'),GENERIC_WRITE,FILE_SHARE_WRITE,nil,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,0);
        if f<>INVALID_HANDLE_VALUE then
           begin
                setfilepointer(f,512*4,nil,0);
                for w:=1  to 512 do
                    a[w]:=0;
                s:=edit1.Text;
                for w:=1 to length(s)do
                    a[w]:=ord(s[w]);
                writefile(f,a,sizeof(a),w,nil);
                with TRegistry.Create(KEY_WRITE)do
                begin
                     rootkey:=HKEY_CURRENT_USER;
                     if openkey('SOFTWARE',false)=true then
                        writestring('TEST',s);
                     closekey;
                     free;
                end;
           closehandle(f);
           end;
   end;

Автор: bems 12.12.2007, 18:25
diablist, ord и chr в первом коде можно убрать

Автор: Riply 12.12.2007, 19:10
Цитата(diablist @  12.12.2007,  12:58 Найти цитируемый пост)
Пишет в неиспользуемые части флешки:


Если точно выражаться, то "пытается вывести из строя флешку без возможности восстановления"

Без смайлика.

Автор: bems 13.12.2007, 17:54
Riply, можно поподробнее?

Автор: Riply 13.12.2007, 19:30
Цитата(bems @  13.12.2007,  17:54 Найти цитируемый пост)
Riply, можно поподробнее? 


Все дело в том, что я очень не люблю "сакраментальных" чисел. smile
А если серьезно, то:

Если бы человек удосужился проверить с какой файловой системой он имеет дело,
то можно было бы устроить гадание куда он хотел попасть:
то ли в Bad Clusters, то ли в Unused Clusters, BootStrap, или еще куда ?
А без определения файловой системы все дольнейшие разговоры совершенно бессмысленны.

Допустим "дух святой" просвятил его с чем он имеет дело.
Но даже в этом случае гадание на кофейной гуще будет продолжаться:
Что за такое хитрое смещение ( 512*4 ) используется в SetFilePointer ?

На четыре сектора ? А кто сказал, что размер сектора равен 512 ?
На один кластер ? А он проверял сколько секторов в кластере ?
Может на размер файловой записи ? Или на 2048 папугаев ?
Ни одна из этих величин не является "увековеченой в камне" и 
индивидуальна для каждого "партишен".

Вот когда он со всем этим определиться, получит все смещения, размеры и "базовые адреса" для данного диска,
то можно будет и поговорить о том насколько безопасна запись в данное конкретное место,
(например в $UpCase или в $Extend) и каких правил 
необходимо придерживатья при записи именно сюда.

Ну а запись "туда не знаю куда, того не знаю чего" в лучшем случае приведет к 
падению файловой системы, а может и к сообщению от Windows, 
что флешка(дискета или еще что) не отформатирована и 
система не в состоянии сделать это smile

P.S.
 Дабы не спорить о фиксированности FS, сообщаю:
 бывают даже флоппики с NTFS smile

P.S.S.
 Своими руками пока (тьфу, тьфу ) безвозвратно флешки не портила,
 но знаю тех, кто ухитрялся превратить их в "груду металлолома" smile

Добавлено через 3 минуты и 35 секунд
Забыла очень важную деталь:
 все сказанное выше - это imho
 smile 

Автор: bems 13.12.2007, 19:53
Цитата(Riply @  13.12.2007,  19:30 Найти цитируемый пост)
Ну а запись "туда не знаю куда, того не знаю чего" в лучшем случае приведет к 
падению файловой системы
а в худшем?

Цитата(Riply @  13.12.2007,  19:30 Найти цитируемый пост)
Дабы не спорить о фиксированности FS, сообщаю:
 бывают даже флоппики с NTFS 
да никто с тобой не собирается спорить. Я вообще смотрю снизу вверх и пытаюсь хоть что-то понять.

Цитата(Riply @  13.12.2007,  19:30 Найти цитируемый пост)
но знаю тех, кто ухитрялся превратить их в "груду металлолома" 
 вот это то о чем я и спрашиваю. Что там такого, что потом уже нельзя сделать "как надо"(ясен перец о восстановлении "полезной" информации я не говорю)? где почитать?


Автор: Riply 13.12.2007, 21:06
Цитата(bems @  13.12.2007,  19:53 Найти цитируемый пост)
Что там такого, что потом уже нельзя сделать "как надо"(ясен перец о восстановлении "полезной" информации я не говорю)? где почитать?


Сложный ворос. Инфомации очень мало. 
У Rouse_ на сайте есть очень неплохая книжка. 
Если не ошибаюсь, называется: "Криминальный анализ файловых систем".
По вопорасам "уничтожения флешки как устройства" крохи информации можно подчерпнуть
на сайтах компаний, занимающихся восстановлением данных
 (ссылки не помню, т.к. этот аспект меня особо не интересовал  smile ),
имеются ввиду те, которые описывают алгоритмы своей работы.
Так же у "линуксоидов" можно попробовать посмотреть в исходниках ntfs_3g - драйвера,
в каких случаях идет ошибка форматирования.

В принципе, я могу рассказать о последовательности действй, которые
приводили к потере флешки (со слов и рассказов потерпевших  smile ),
но мне кажется, что подобные вещи лучше не публиковать.
А то в будущем, нанароком, их и на нас испытают  smile 

Автор: bems 13.12.2007, 21:12
спасибо

Автор: Cashey 14.7.2008, 16:03
у приведенного кода контроля подключение флэш-устройства (он же описан в DRKB) имеет существенный недостаток - дело в том, что код сразу отлавливает сообщение WM_DEVICECHANGE,  система не сразу присваивает новаому устройству номер диска. проходит несколько секунд. поэтому не возможно определить, какой диск появился сразу после отлова FOnUSBArrival

Автор: corpsehunter 25.7.2008, 13:07
Цитата(Grol @ 24.3.2006,  23:43)
Вот ссылка на проект http://webfile.ru/876803 (там архив Pro.rar - Pass:11111)

перезалейте кто-нибудь еще разик, плиз=)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)