如何检测可移动磁盘驱动器何时(断开)连接到系统?如何获取挂载路径(适用于 Linux)和驱动器号(适用于 Windows)?
编辑:有没有办法检测当前连接的设备?
如何检测可移动磁盘驱动器何时(断开)连接到系统?如何获取挂载路径(适用于 Linux)和驱动器号(适用于 Windows)?
编辑:有没有办法检测当前连接的设备?
对于 Windows,API RegisterDeviceNotification将在添加 USB 设备时通知您。有关卷的信息在DEV_BROADCAST_VOLUME 结构中给出。dbcv_unitmask
给出驱动器号。
您可以从外壳获取更改通知(添加/删除驱动器)。您可以使用此 Delphi 代码作为文档:
unit UnitChangeNotify;
interface
uses
Windows, Messages, SysUtils, Classes, ShlObj, Types;
type
SHChangeNotifyEntry = record
pidlPath : PItemIDList;
bWatchSubtree : Boolean;
end;
TChangeEventType = (
cnAssocchanged,
cnAttributes,
cnCreate,
cnDelete,
cnDriveAdd,
cnDriveAddGui,
cnDriveRemoved,
cnMediaInserted,
cnMediaRemoved,
cnMkdir,
cnNetShare,
cnNetUnshare,
cnRenameFolder,
cnRenameItem,
cnRmdir,
cnServerDisconnect,
cnUpdateDir,
cnUpdateImage,
cnUpdateItem );
TChangeNotifyEvent = procedure( Sender: TObject; Event: TChangeEventType; const Paths: TStringDynArray ) of object;
TChangeNotify = class( TComponent )
private
FHWnd: HWND;
FRegID: THandle;
FEntry: SHChangeNotifyEntry;
FOnChange: TChangeNotifyEvent;
function GetActive (): Boolean;
procedure SetActive ( const Value: Boolean );
procedure WndProc ( var Msg: TMessage );
procedure DoEvent ( Event: TChangeEventType; const Paths: TStringDynArray ); virtual;
public
constructor Create ( Aowner: TComponent ); override;
destructor Destroy; override;
property Active: Boolean read GetActive write SetActive;
property OnChange: TChangeNotifyEvent read FOnChange write FOnChange;
end;
const
SHCNF_ACCEPT_INTERRUPTS = $0001;
SHCNF_ACCEPT_NON_INTERRUPTS = $0002;
SHCNF_NO_PROXY = $8000;
function SHChangeNotifyRegister( hWnd: HWND; fSources: Integer; wEventMask: DWORD; uMsg: UINT; cItems: integer; const Items: SHChangeNotifyEntry ): THandle; stdcall;
function SHChangeNotifyDeregister( hRegID: THandle ) : BOOL; stdcall;
function SHILCreateFromPath( Path: Pointer; PIDL: PItemIDList; var Attributes: ULONG ): HResult; stdcall;
implementation
const Shell32DLL = 'shell32.dll';
function SHChangeNotifyRegister; external Shell32DLL index 2;
function SHChangeNotifyDeregister; external Shell32DLL index 4;
function SHILCreateFromPath; external Shell32DLL index 28;
{ TChangeNotify }
constructor TChangeNotify.Create( Aowner: TComponent );
begin
inherited Create( AOwner );
end;
destructor TChangeNotify.Destroy;
begin
Active := False;
inherited Destroy;
end;
procedure TChangeNotify.DoEvent( Event: TChangeEventType; const Paths: TStringDynArray );
begin
if Assigned( FOnChange ) then FOnChange( Self, Event, Paths );
end;
function TChangeNotify.GetActive(): Boolean;
begin
Result := FHWnd <> 0;
end;
procedure TChangeNotify.SetActive( const Value: Boolean );
begin
if Value = GetActive() then Exit;
if Value then begin
FHWnd := AllocateHWnd( WndProc );
FEntry.pidlPath := nil;
FEntry.bWatchSubtree := True;
FRegID := SHChangeNotifyRegister( FHWnd, SHCNF_ACCEPT_INTERRUPTS or SHCNF_ACCEPT_NON_INTERRUPTS,
SHCNE_ALLEVENTS, WM_USER, 1, FEntry );
if FRegID = 0 then begin
DeallocateHWnd( FHWnd );
FHWnd := 0;
RaiseLastOSError();
end;
end else begin
SHChangeNotifyDeregister( FRegID );
FRegID := 0;
DeallocateHWnd( FHWnd );
FHWnd := 0;
end;
end;
procedure TChangeNotify.WndProc( var Msg: TMessage );
type
PPITEMIDLIST = ^PITEMIDLIST;
var
Event: TChangeEventType;
i: Integer;
Paths: TStringDynArray;
P: PPITEMIDLIST;
const
EventBits: array [ TChangeEventType ] of DWORD = (
SHCNE_ASSOCCHANGED,
SHCNE_ATTRIBUTES,
SHCNE_CREATE,
SHCNE_DELETE,
SHCNE_DRIVEADD,
SHCNE_DRIVEADDGUI,
SHCNE_DRIVEREMOVED,
SHCNE_MEDIAINSERTED,
SHCNE_MEDIAREMOVED,
SHCNE_MKDIR,
SHCNE_NETSHARE,
SHCNE_NETUNSHARE,
SHCNE_RENAMEFOLDER,
SHCNE_RENAMEITEM,
SHCNE_RMDIR,
SHCNE_SERVERDISCONNECT,
SHCNE_UPDATEDIR,
SHCNE_UPDATEIMAGE,
SHCNE_UPDATEITEM );
EventPIDLCount: array [ TChangeEventType ] of Integer = (
2,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
2,
2,
1,
1,
1,
1,
1 );
begin
case Msg.Msg of
WM_USER: begin
// lParam = eventmask
// wParam = array of PIDLs with
for Event := Low( Event ) to High( Event ) do begin
if EventBits[ Event ] and msg.LParam = EventBits[ Event ] then begin
SetLength( Paths, EventPIDLCount[ Event ] );
P := PPITEMIDLIST( Msg.WParam );
for i := 0 to High( Paths ) do begin
SetLength( Paths[ i ], MAX_PATH );
if not SHGetPathFromIDList( P^, PChar( Paths[ i ] ) ) then Paths[ i ] := '' else Paths[ i ] := PChar( Paths[ i ] );
Inc( P );
end;
DoEvent( Event, Paths );
Break;
end;
end;
end;
end;
DefaultHandler( Msg );
end;
end.