PDA

View Full Version : تشخیص اضافه شدن درایو Removable جدید



Felony
یک شنبه 15 آذر 1388, 20:03 عصر
:لبخندساده:سلام ،

همونطور که میدونید به وسیله ی تابع GetDriveType میشه تشخیص داد که یک درایو از چه نوعی هست .

حالا میخوام ببینم وقتی ما یه درایو Removable جدید ( مثل کول دیسک ) به سیستم وصل میکنیم ، آیا پیغام خاصی به سیستم عامل ارسال میشه ؟ یعنی میشه این پیغام رو هوک کرد و فهمید که یک درایو جدید وصل شده ؟ یا در مورد جدا کردن درایو Removable از سیستم ، آیا وقتی کول دیسک رو از سیستم جدا میکنیم پیغامی به سیستم عامل ارسال میشه که بشه هوکش کرد ؟

میخوام اضافه شدن درایو جدید رو تشخیص بدم ، البته میشه با یه تایمر هر چند وقت چک کنم که درایو جدیدی اضافه شده یا نه ولی این کار برای برنامم مشکل ساز میشه ، اگر کسی از وجود چنین پیغامی اطلاع داره ممنون میشم کمک کنه .

Felony
یک شنبه 15 آذر 1388, 20:11 عصر
من تو MSDN گشتم ، قهمیدم باید از تابع RegisterDeviceNotification استفاده کنم ، کسی نمونه ای نداره ؟

vcldeveloper
دوشنبه 16 آذر 1388, 02:43 صبح
کد زیر نمونه ساده شده مثال MSDN (http://msdn.microsoft.com/en-us/library/aa363432%28VS.85%29.aspx) برای کار با RegisterDeviceNotification (http://msdn.microsoft.com/en-us/library/aa363431%28VS.85%29.aspx) هست.

در کد زیر، با کلیک بر روی btnRegister، تابع RegisterDeviceNotification برای دستگاه های USB فراخوانی میشه، و در صورت اضافه شدن یک دستگاه USB (مثلا یک Flash Disk) به سیستم، یا جدا شدن آن از سیستم، پیام مناسب به کاربر داده میشه.

دقت کنید که header فایل Dbt.h بصورت استاندارد در دلفی ترجمه نشده، و شما یا باید خودتون تعریف توابع مربوطه و ساختار داده های استفاده شده را ترجمه کنید، یا از ترجمه های موجود استفاده کنید. در کد زیر از ترجمه ارائه شده توسط تیم JEDI در یونیتی با نام JwaDbt.pas استفاده شده. شما می تونید مجموعه کامل headerهای ترجمه شده مربوط به Windows API توسط تیم JEDI را از لینک زیر دانلود کنید:
http://sourceforge.net/projects/jedi-apilib/


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls,
JwaDbt;

type
TForm1 = class(TForm)
btnRegister: TButton;
procedure btnRegisterClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FDeviceNotifyHandle : HDEVNOTIFY;
procedure WmDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnRegisterClick(Sender: TObject);
var
NotificationFilter: DEV_BROADCAST_DEVICEINTERFACE;
InterfaceClassGuid : TGUID;
begin
//USB device GUID
InterfaceClassGuid := StringToGUID('{25dbce51-6c8f-4a72-8a6d-b54c2b4fc835}');
//Initialize notification filter data structure
FillMemory(@NotificationFilter,SizeOf(Notification Filter),0);
NotificationFilter.dbcc_size := SizeOf(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid := InterfaceClassGuid;
//Register device notifcation
FDeviceNotifyHandle := RegisterDeviceNotification(Self.Handle,
@NotificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE);
if Assigned(FDeviceNotifyHandle) then
ShowMessage('USB device notification is registered.')
else
RaiseLastOSError;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
//Unregister device notify
if Assigned(FDeviceNotifyHandle) then
UnregisterDeviceNotification(FDeviceNotifyHandle);
end;

procedure TForm1.WmDeviceChange(var Msg: TMessage);
begin
case Msg.WParam of
DBT_DEVICEARRIVAL : ShowMessage('USB device is attached.');
DBT_DEVICEREMOVECOMPLETE : ShowMessage('USB device is detached.');
end;
end;

end.

Felony
دوشنبه 16 آذر 1388, 06:33 صبح
ممنون علی آقا ، حالا میخوام ببینم میشه نام درایو جدید رو هم تشخیص داد ؟ یعنی زمانی که درایو جدید وصل میشه به جای اینکه پیغام نمایش بدیم بتونیم نام درایو جدید رو به دست بیاریم و نمایش بدیم .

ممنون .

vcldeveloper
دوشنبه 16 آذر 1388, 08:55 صبح
یعنی زمانی که درایو جدید وصل میشه به جای اینکه پیغام نمایش بدیم بتونیم نام درایو جدید رو به دست بیاریم و نمایش بدیم .
اطلاعات تکمیلی درباره وسیله متصل شده از طریق پارامتر lparam پیام WM_DEVICECHANGE در دسترس هست. این پارامتر حاوی یک اشاره گر به رکورد DEV_BROADCAST_DEVICEINTERFACE هست.

Felony
دوشنبه 16 آذر 1388, 10:07 صبح
علی آقا من یه کامپوننت برای این کار نوشتم ( البته قسمتهایی از این کد رو از اینترنت گیر آوردم ) و بدون نیاز به اون فایل ترجمه ی JEDI کار میکنه ، ( سورس و دمو کامپوننت رو هم ضمیمه کردم ) ، میشه یه راهنمایی بکنید تا من بتونم سورس کامپوننت رو تغییر بدم تا کامپوننت بتونه نام داریو وصل شده یا جدا شده از سیستم رو هم برگردونه ؟

ممنون .

Felony
دوشنبه 16 آذر 1388, 13:12 عصر
علی آقا من خواستم مشکل شناسایی درایو رو تو برنامم برای خودم به صورت زیر حل کنم که باز به مشکل خوردم :

در زمان اتصال یک درایو جدید یک فایل INI ساختم و با یک حلقه از A تا Z درایو ها رو چک کردم و اونهایی رو که Removable بود تو فایل True = INI قرار دادم و در زمان جدا شدن یک درایو Removable هم بر عکس یعنی False کردمشون ، ولی فهمیدم که یک مشکل به وجود میاد ، ببینید وقتی من پیغام اتصال درایو جدید رو هوک میکنم و تو برنامم یه کدی رو در این زمان اجرا میکنم ، سیستم عامل تا زمانی که کار برنامه ی من تمام نشده درایو رو تو MyComputer نمایش نمیده و کار شناسایی درایو تا اتمام کار برنامه ناقص میمونه به همین خاطر تو برنامه وقتی با کد IF GetDriveType(PChar(i+':') = Drive_Removable then درایوها رو چک میکنم داریو جدید چون هنوز کامل شناسایی نشده تو کد هم شناسایی نمیشه .

یک نمونه هم از این مشکل ضمیمه کردم ، اگر ممکنه راهنمایی بفرمایید .

FiACKER
دوشنبه 16 آذر 1388, 13:28 عصر
حالا در مورده چک کردنه درایو چه راهه حلی وجود داره ؟
حتما تا حالا چک کردید که اگه یه درایو Removable ی رو که Eject شده رو چک کنیم ببینیم که نوعش چیه یا فلان فایل توشه یا نه ، یه پیغام خطا ایجاد می شه که توسط برنامه ی ما هم قابل کنترل نیست (یعنی نمتونی با try expect از خطا جلوگیری کنید).

ایا راه حلی دارید ؟

http://barnamenevis.org/forum/attachment.php?attachmentid=40838&stc=1&d=1260223211

Felony
دوشنبه 16 آذر 1388, 13:46 عصر
حالا در مورده چک کردنه درایو چه راهه حلی وجود داره ؟
حتما تا حالا چک کردید که اگه یه درایو Removable ی رو که Eject شده رو چک کنیم ببینیم که نوعش چیه یا فلان فایل توشه یا نه ، یه پیغام خطا ایجاد می شه که توسط برنامه ی ما هم قابل کنترل نیست (یعنی نمتونی با try expect از خطا جلوگیری کنید).

ایا راه حلی دارید ؟

http://barnamenevis.org/forum/attachment.php?attachmentid=40838&stc=1&d=1260223211

میتونید اول چک کنید ببینید درایو آماده هست یا نه :


var
EMode: Word;
begin
EMode := SetErrorMode(SEM_FAILCRITICALERRORS) ;
try
if DiskSize(Ord('N')-$40) <> -1 then
ShowMessage('Disk in drive N: !')
else
ShowMessage('No disk in drive N: !') ;
finally
SetErrorMode(EMode) ;
end;

vcldeveloper
دوشنبه 16 آذر 1388, 14:10 عصر
یک نمونه کد برای بدست آوردن نام دستگاه USB در هنگام اتصال یا قطع اتصال آن از سیستم در لینک زیر هست:
http://www.winu.cn/space-14160-do-blog-id-1737.html

برای به دست آوردن نام دستگاه باید اطلاعاتی از رجیستری خوانده بشه، یا از توابع SetupDiXXX ویندوز استفاده بشه، چون نامی که به همراه WM_DEVICENOTIFY برگشت داده میشه فقط یک کد هست که شامل کد سازنده و شماره یکتا دستگاه میشه، نه نام دستگاه.
در سورس بالا از رجیستری برای به دست آوردن نام دستگاه از روی کد سازنده + شماره دستگاه استفاده شده.

FiACKER
دوشنبه 16 آذر 1388, 22:31 عصر
میتونید اول چک کنید ببینید درایو آماده هست یا نه :


var
EMode: Word;
begin
EMode := SetErrorMode(SEM_FAILCRITICALERRORS) ;
try
if DiskSize(Ord('N')-$40) <> -1 then
ShowMessage('Disk in drive N: !')
else
ShowMessage('No disk in drive N: !') ;
finally
SetErrorMode(EMode) ;
end;

اقا واقعا ممنون.
خیلی دنبالش بودم.
شما هم دارید مثله بچه های مجید انلاین انتی ویروس می نویسید ؟
امیدوارم موفق بشید:تشویق:

Felony
دوشنبه 16 آذر 1388, 22:43 عصر
اقا واقعا ممنون.
خیلی دنبالش بودم.
شما هم دارید مثله بچه های مجید انلاین انتی ویروس می نویسید ؟
امیدوارم موفق بشید
خیر یک نرم افزار امنیتی هست که دارم روش کار میکنم و نسخه ی اولیه ی اون آماده شده و در صورت تایید مدیران در بخش معرفی نرم افزار قرار میگیره .
ممنون .