2009-12-18 5 views
4

USB 플래시 드라이브를 삽입하고 제거 할 때 감지 할 수있는 몇 가지 코드 및 .pas 파일을 발견했습니다. 일부는 모든 종류의 좋은 정보를 제공하지만 필요한 것은 장치의 고유 한 일련 번호가 아니라 볼륨의 일련 번호입니다.플래시 장치의 고유 일련 번호를 찾는 방법은 무엇입니까?

내 현재 .pas 파일 (내가 발견 한 위치를 기억하지 못함)도 SD 카드 (좋아하는 것)를 감지하는 것 같습니다. 모양을 원할 경우 여기에서 찾을 수 있습니다 (드라이브 번호 만 반환하고 삽입/제거 만 가능).

unit UsbDetector; 

interface 

uses Classes; 

type 
    TUsbDriveChanged = procedure (Sender: TObject; Drive: string; Attached: boolean) of object; 

procedure StartUsbDetector(NotifyProc: TUsbDriveChanged); 
procedure StopUsbDetector; 

implementation 

uses Windows, Messages, Forms, SysUtils; 

type 
    TUSBDetector = class(TObject) 
    private 
    fUsbDriveChanged: TUsbDriveChanged; 
    protected 
    procedure DeviceChanged(Msg: UINT; wParam, lParam: Longint); 
    procedure DoUsbDriveChanged(Drive: string; Attached: Boolean); dynamic; 
    public 
    constructor Create(NotifyProc: TUsbDriveChanged); 
    destructor Destroy; override; 
    property OnUsbDriveChanged: TUsbDriveChanged read fUsbDriveChanged; 
    end; 

var mUSBDetector: TUSBDetector; 

procedure StartUsbDetector(NotifyProc: TUsbDriveChanged); 
begin 
    if not Assigned(mUsbDetector) then 
    mUsbDetector := TUsbDetector.Create(NotifyProc); 
end; 

procedure StopUsbDetector; 
begin 
    FreeAndNil(mUsbDetector); 
end; 

{----------------------------------------------------------------------------} 
// Device constants 
const 
    DBT_DEVICEARRIVAL   = $00008000; 
    DBT_DEVICEREMOVECOMPLETE = $00008004; 
    DBT_DEVTYP_VOLUME   = $00000002; 

// Device structs 
type 
    _DEV_BROADCAST_HDR   = packed record 
    dbch_size:    DWORD; 
    dbch_devicetype:  DWORD; 
    dbch_reserved:   DWORD; 
    end; 
    DEV_BROADCAST_HDR   = _DEV_BROADCAST_HDR; 
    TDevBroadcastHeader  = DEV_BROADCAST_HDR; 
    PDevBroadcastHeader  = ^TDevBroadcastHeader; 

type 
    _DEV_BROADCAST_VOLUME  = packed record 
    dbch_size:    DWORD; 
    dbch_devicetype:  DWORD; 
    dbch_reserved:   DWORD; 
    dbcv_unitmask:   DWORD; 
    dbcv_flags:    WORD; 
    end; 
    DEV_BROADCAST_VOLUME  = _DEV_BROADCAST_VOLUME; 
    TDevBroadcastVolume  = DEV_BROADCAST_VOLUME; 
    PDevBroadcastVolume  = ^TDevBroadcastVolume; 

var 
    fPrevWndProc: TFNWndProc = nil; 

function UsbWndProc(hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; stdcall; 
begin 
    Result := CallWindowProc(fPrevWndProc, hWnd, Msg, wParam, lParam); 
    if (Msg = WM_DEVICECHANGE) and (mUsbDetector <> nil) then 
    mUsbDetector.DeviceChanged(Msg, wParam, lParam); 
end; 

constructor TUSBDetector.Create(NotifyProc: TUsbDriveChanged); 
begin 
    inherited Create; 
    fUsbDriveChanged := NotifyProc; 
    if not Assigned(fPrevWndProc) then 
    begin 
    fPrevWndProc := TFNWndProc(GetWindowLong(Application.Handle, GWL_WNDPROC)); 
    SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(@UsbWndProc)); 
    end; 
end; 

destructor TUSBDetector.Destroy; 
begin 
    //SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(@fPrevWndProc)); 
    inherited Destroy; 
end; 

procedure TUSBDetector.DeviceChanged(Msg: UINT; wParam, lParam: LongInt); 
var 
    lpdbhHeader: PDevBroadcastHeader; 
    lpdbvData: PDevBroadcastVolume; 
    dwIndex: Integer; 
    lpszDrive: string; 
begin 
    // Get the device notification header 
    lpdbhHeader := PDevBroadcastHeader(lParam); 
    // Handle the message 
    lpszDrive := ''; 
    case WParam of 
    DBT_DEVICEARRIVAL: {a USB drive was connected} 
    begin 
     if lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME then 
     begin 
     lpdbvData := PDevBroadcastVolume(lParam); 
     for dwIndex := 0 to 25 do 
     begin 
      if (lpdbvData^.dbcv_unitmask shr dwIndex) = 1 then 
      begin 
      lpszDrive := lpszDrive + Chr(65 + dwIndex) + ':\'; 
      break; 
      end; 
     end; 
     DoUsbDriveChanged(lpszDrive, True); 
     end; 
    end; 
    DBT_DEVICEREMOVECOMPLETE: {a USB drive was removed} 
    begin 
     if lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME then 
     begin 
     lpdbvData := PDevBroadcastVolume(lParam); 
     for dwIndex := 0 to 25 do 
     begin 
      if (lpdbvData^.dbcv_unitmask shr dwIndex) = 1 then 
      begin 
      lpszDrive := lpszDrive + Chr(65 + dwIndex) + ':\'; 
      break; 
      end; 
     end; 
     DoUsbDriveChanged(lpszDrive, False); 
     end; 
    end; 
    end; 
end; 

procedure TUSBDetector.DoUsbDriveChanged(Drive: string; Attached: Boolean); 
begin 
    if Assigned(fUsbDriveChanged) then 
    fUsbDriveChanged(Self, Drive, Attached); 
end; 

end. 

P.S. 코드 강조 표시가 실패했습니다.

모두 모두; 이동식을 삽입하거나 제거 할 때 드라이브 문자와 고유 한 일련 번호를 가져옵니다. 이미 주어진 코드를 WMI 호출 "where Index = found_index"와 결합 할 수 있습니다.

**** EDIT! **** RRUZ가 제공 한 코드에서 "where"절이 제거되었습니다. 마침내 배열을 처리하는 방법을 알아 냈으므로 모든 이동식 미디어를 가져 오기 위해 Capabilities [i] = 7을 찾는 데 사용했습니다. 이제이 코드를 위의 코드와 연결해야합니다. 인덱스를 사용하여 생각하고 있지만 GetDrive MapInfo 사용하는 방법을 모르겠습니다. 당신이 드라이브 편지를 얻는 것에 대한 예제를 제게 줄 수 있다면, 제 질문이 풀립니다.

+1

@ 대니얼,이 질문에 체크하십시오. http://stackoverflow.com/questions/1687239/getting-connected-usb-info-with-delphi-on-vista – RRUZ

+0

그래,하지만 내가 원하는 걸 잊어 버렸어. 표준 방법 (있는 경우). 나는 대안이 없다면 이것을 사용할 수 있다고 생각한다. –

+0

좋습니다. 작동합니다. 그러나 USB 스틱 만 감지합니다. 그리고 이미 기존 유닛과 연결할 수있는 방법이 없습니다. –

답변

4

으로 WMI 라이브러리를 사용할 수 있습니다. Magenta Systems은 WMI 쿼리 사용시 발생하는 대부분의 문제를 해결합니다. 무료 다운로드에는 API 및 하트 컨텐츠에 대한 쿼리를 수행 할 수있는 소스 및 예제 프로젝트가 포함되어 있습니다. 공식 Microsoft API documentation에 대한 링크를 유지하면 어떤 쿼리를 실행하여 어떤 정보를 얻을 수 있는지 알려줄 것입니다. 구문 쿼리와 같은 SQL을 사용하여 클래스를 쿼리하는 데 관심이 있습니다. 쿼리

SELECT * FROM Win32_DiskDrive Where InterfaceType = 'USB' 

을 실행하는 예를 들어

는 현재 시스템에 연결된 USB 장치의 모든에 대한 풍부한 정보를 반환합니다. 그런 다음 PNPDeviceID를 고유 식별자로 사용할 수 있습니다.

EDIT 내가 손에 가지고있는 유일한 USB 장치를 확인한 결과 "u"라는 하드웨어 일련 번호가 반환되었지만 매우 길고 유효한 PNPDeviceID가 일련 번호를 포함하고있는 것으로 나타났습니다. 이것이 내가 해당 필드를 제안한 이유입니다. 당신은 Win32_LogicalDisk에 대해 쿼리를 수행하여 드라이브 문자를 얻을 수

EDIT 당신은 또한 Win32_DiskDriveWin32_DiskPartition 사이의 매핑을 포함 Win32_DiskDriveToDiskPartition을 조회 할 수 있습니다. 마지막으로 Win32_LogicalDiskToPartition은 논리적 디스크를 파티션에 매핑하므로 물리적 USB 드라이브를 특정 드라이브 문자에 연결할 수 있습니다.

+0

예, 그 행에있는 것이지만 질문에 대한 설명을 살펴 보시기 바랍니다. 모든 종류의 이동식 장치 (SD 카드 포함)가 필요합니다.또한, 그러한 장치가 삽입 (및 제거) 될 때이 정보를 얻을 수 있어야하며, 문제의 코드와 결합 할 수 있습니까? –

+0

where 절에 아무 것도 추가 할 필요가 없으며 컴퓨터에 연결된 모든 디스크 드라이브 장치에 대한 레코드를 반환합니다. – skamradt

+0

알아. 그게 내가하는 일이야. 그러나 필요한 것은 드라이브 문자뿐입니다. –

관련 문제