全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1566
推到 Plurk!
推到 Facebook!

USB-s eszközök kezelése

 
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-07-08 01:41:09 IP:218.175.xxx.xxx 未訂閱
http://www.codexonline.hu/CodeX8/alap/hardcore/MagyarAttila/USBeszkozok.htm     
 USB-s eszközök kezelése    Nemrég egy olyan feladatot kaptam hogy közvetlenül  USB-s nyomtatóra írjak ki egy fájlt.    Sok utánajárás és keresgélés után jöttem csak rá a megoldásra, ezért gondoltam leírom, hogy is lehet megcsinálni. A problémát WindowsXP alatt kellett megoldanom, ezért a példaprogram is az XP-s megoldást mutatja be. A megvalósítás pedig Borland Delphi rendszerben történt.    Minden USB-s eszköznek van egy egyedi azonosítója (GUID) és egy DeviceName-je. Ha meg akarjuk nyitni az eszközt, akkor ezt a DeviceName-et kell átadni a CreateFile() WinAPI függvénynek. A DeviceName-et a GUID-ból tudhatjuk meg, azt pedig a registry-ből olvashatjuk ki. Egy olyan megoldást fogok bemutatni, ami a számítógéphez csatlakoztatott USB-s eszközöket kilistázza a DeviceName-mel. Ehhez a SetupApi.dll-ben található függvényeket fogjuk használni.    WinXP alatt a következő helyen vannak az USB-s bejegyzések: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB    A Vid-del kezdődő bejegyzéseken belül található egy DeviceParameters, ami tartalmazza a SymbolicName kulcsot.     Aminek az értéke pl.    \??\USB#Vid_03f0&Pid_2304#TH1CQ1F095#{a5dcbf10-6530-11d2-901f-00c04fb951ed}    A kapcsok közötti rész a GUID {a5dcbf10-6530-11d2-901f-00c04fb951ed}    A SymbolicName-ből egy kis módosítással megkaphatjuk a DeviceName-t, ha kicseréljük az 1-4. karaktereket erre: \\?\.    Ez már egy érvényes DeviceName amit megadhatunk a CreateFile() függvénynek    \\?\USB#Vid_03f0&Pid_2304#TH1CQ1F095#{a5dcbf10-6530-11d2-901f-00c04fb951ed}    var nyomtatohw: string;    ...    nyomtatohw := ‘\\?\USB#Vid_03f0&Pid_2304#TH1CQ1F095#{a5dcbf10-6530-11d2-901f-00c04fb951ed}’    h:=CreateFile(pchar(nyomtatohw), GENERIC_READ OR GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);    ...    De sajnos ilyet nem drótozhatunk bele konstans módon egy programba, ezért kénytelenek vagyunk kilistázni az összes eszközt egy leírással együtt és így a felhasználó ki tudja választani a megfelelőt (az én esetemben a nyomtatót)    Ezt, a function listUSB(var count: integer):ADeviceNames;  függvénnyel csináltam meg.    Ez viszont egy AdeviceNames típusú rekordtömbben adja vissza a neveket a leírással.    type TDeviceNames = record     Real,     Device : string[255];    end;    type ADeviceNames = array of TDeviceNames;    A következő függvénnyel ellenőrzöm, hogy az eszköz csatlakoztatva van-e a számítógéphez.    A PGUID egy GUID típusú változóra mutató pointer, aminek a feltöltésére van egy makró, de nekem ez sehogy sem működött, ezért ügyködtem fél oldalon keresztül a manuális feltöltéssel.    A CheckGuid() függvényt a listUSB() függvény használja miután kikereste a registry-ből a GUID-ot és meghatározta belőle a DeviceName-et, csak akkor tárolja el az AdeviceNames tömbben ha a CheckGuid() függvény true értékkel tér vissza, ami azt jelenti hogy az eszköz a számítógéphez van kötve és be is van kapcsolva. A SetupApi.dll-es rutinokhoz nem fűznék hosszabb megjegyzést, ezekről van részletes leírás a Microsoft weboldalán is.    function CheckGuid(guid, DeviceName: string):boolean;    var     sub: Tstrings;     d1 : cardinal;     d2, d3, d4: word;     d: byte;     d51, d52, d53, d54, d55, d56: byte;     dd: string;     i, f, m: cardinal;     needed:cardinal;     hInfo: HDEVINFO;     L_GUID: PGUID;     ii: DWORD;     Interface_Info: SP_INTERFACE_DEVICE_DATA;     detail: PSP_INTERFACE_DEVICE_DETAIL_DATA;     Devices: Tstrings;     name: pchar;    Begin     if length(guid)<>36 then begin CheckGuid:=false; exit; end; //ellenőrzések hogy valódi e a GUID     sub:=TStringList.Create;     sub:=explode('-', guid);       if sub.Count<>5  then begin CheckGuid:=false; exit; end;     for i:=0 to sub.Count-2 do      sub.Strings[i]:='$'    sub.Strings[i];     d1 := StrToInt(sub.Strings[0]);     d2 := StrToInt(sub.Strings[1]);     d3 := StrToInt(sub.Strings[2]);     d4 := StrToInt(sub.Strings[3]);     SetLength(dd, 3);     dd[1]:='$';     dd[2]:= sub.Strings[4][1];     dd[3]:= sub.Strings[4][2];     d51:=StrToInt(dd);     dd[2]:= sub.Strings[4][3];     dd[3]:= sub.Strings[4][4];     d52:=StrToInt(dd);     dd[2]:= sub.Strings[4][5];     dd[3]:= sub.Strings[4][6];     d53:=StrToInt(dd);     dd[2]:= sub.Strings[4][7];     dd[3]:= sub.Strings[4][8];     d54:=StrToInt(dd);     dd[2]:= sub.Strings[4][9];     dd[3]:= sub.Strings[4][10];     d55:=StrToInt(dd);     dd[2]:= sub.Strings[4][11];     dd[3]:= sub.Strings[4][12];     d56:=StrToInt(dd);     SetLength(dd, 0);     getmem(L_GUID, 16); getmem(name, 255);     L_GUID.D1:=d1;     L_GUID.D2:=d2;     L_GUID.D3:=d3;     asm      mov ax, d4      mov d, ah     end;     L_GUID.D4[0]:=d;     asm      mov ax, d4      mov d, al     end;     L_GUID.D4[1]:=d;     L_GUID.D4[2]:=d51;     L_GUID.D4[3]:=d52;     L_GUID.D4[4]:=d53;     L_GUID.D4[5]:=d54;     L_GUID.D4[6]:=d55;     L_GUID.D4[7]:=d56;     hInfo := SetupDiGetClassDevs(L_GUID, nil, 0,  (DIGCF_PRESENT OR DIGCF_INTERFACEDEVICE));     if  DWORD(hInfo)=INVALID_HANDLE_VALUE then     begin      freemem(L_GUID, 16);      freemem(name, 255);      checkGuid:=false;      exit;     end;     Devices:= TstringList.Create;     i:=0;     while true do     begin       Interface_Info.cbSize := sizeof(SP_INTERFACE_DEVICE_DATA);       // Enumerate device       if not SetupDiEnumDeviceInterfaces(hInfo, nil, L_GUID, i, @Interface_Info) then       begin         SetupDiDestroyDeviceInfoList(hInfo);         m := i;         break;       end;        // get the required length       SetupDiGetDeviceInterfaceDetail(hInfo, @Interface_Info, nil, 0, @needed, nil);       getmem(detail, needed);//detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(needed);       if (detail=nil) then       begin        SetupDiDestroyDeviceInfoList(hInfo);        m := i;        break;       end;    // fill the  device details       detail.cbSize := sizeof(TSP_INTERFACE_DEVICE_DETAIL_DATA);       if (not SetupDiGetDeviceInterfaceDetail(hInfo, @Interface_Info, detail ,needed, @needed, nil)) then       begin         freemem(detail, cardinal(needed));         SetupDiDestroyDeviceInfoList(hInfo);         m := i;         break;       end;       f:=0;       StrCopy(name, detail.DevicePath);       freemem(detail, cardinal(needed));       Devices.Add(name); // keep a copy of each device name       inc(i);     end;     freemem(L_GUID, 16);     freemem(name, 255);     checkGuid:=false;     if Devices.Count = 0 then begin  checkGuid:=false; Devices.Free; exit; end;     for i:=0 to Devices.Count-1 do      if UpperCase(Devices.Strings[i]) = UpperCase(DeviceName) then      begin        checkGuid:=true;        break;      end;     Devices.Free;    End;    Ez pedig a listUSB függvény ami visszaadja az USB-s listát (AdeviceNames) és az eszközök számát (count). Ide kellenek a SetupApi-s függvények.    function listUSB(var count: integer):ADeviceNames;    var     sub, vid: TStrings;     DeviceNamesArray: ADeviceNames;     i, k, j, c, index, max: integer;     dis1, dis2, s, guid: AnsiString;     reg: Tregistry;    begin     count := 0;     listUSB:=nil;     reg:=Tregistry.Create; reg.RootKey :=  HKEY_LOCAL_MACHINE;     if not reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Enum\USB') then      begin       ShowMessage('Can''t open in registry: \SYSTEM\CurrentControlSet\Enum\USB'); reg.Free;       exit;     end;     sub := TstringList.Create;     vid := TstringList.Create;     SetLength(DeviceNamesArray, 0);     reg.GetKeyNames(sub);     if ( sub.Count=0 ) then begin       ShowMessage('Can''t open in registry: \\SYSTEM\\CurrentControlSet\\Enum\\USB...');              reg.Free;       exit;      end;     max := sub.Count;     index:=0;     for i:=0  to max-1 do     begin                    //Vid-del kezdődő bejegyzéseket keresünk      if ( (length(sub.Strings[i])>=3) and (UpperCase(sub.Strings[i][1])='V') and (UpperCase(sub.Strings[i][2])='I') and (UpperCase(sub.Strings[i][3])='D') ) then      begin        if not (reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Enum\USB\' sub.Strings[i]))   then          begin             ShowMessage('Can''t open key in registry: \SYSTEM\CurrentControlSet\Enum\USB\' sub.Strings[i]);                 reg.Free();           exit        end;         reg.GetKeyNames(vid); //VID_         for c:=0 to vid.Count-1 do  //open SubKeys        begin         if not (reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Enum\USB\' sub.Strings[i])) then          begin           ShowMessage('Can''t open key in registry: \SYSTEM\CurrentControlSet\Enum\USB\' sub.Strings[i]);               reg.Free();           exit         end;          if not (reg.OpenKeyReadOnly(vid.Strings[c])) then continue;  //VID_ 0.         dis1:= reg.ReadString('LocationInformation');   //Az eszköz leírása         dis2:= reg.ReadString('DeviceDesc');               //Az eszköz leírása         if length(dis1)= 0 then dis1:='notfound'; //Real_ 0dik         if length(dis2)= 0 then dis2:='notfound'; //Real_ 0dik         if not (reg.OpenKeyReadOnly('Device Parameters')) then continue;         s := reg.ReadString('SymbolicName');                   if (length(s) = 0) then continue;          Delete(s, 1, 4); s:='\\?\' s;       //a szimbolikus névből előállítjuk a GUID-ot és a DeviceName-t         guid:=s; Delete(guid, 1, pos('{', guid)); delete(guid, length(guid), length(guid));         if not checkGuid(guid, s) then continue; //ha az eszköz használatban van akkor eltároljuk         SetLength(DeviceNamesArray, length(DeviceNamesArray) 1);         DeviceNamesArray[index].Real:=dis1   ' '  dis2;         DeviceNamesArray[index].Device:=s;         inc(index);        end;      end;     end;     if (index=0) then begin ShowMessage('USB Devices not found'); reg.Free; exit; end;     count := index;     listUSB:=DeviceNamesArray;    end;        Innen már csak ki kell írnunk a listát és a kiválasztott elem DeviceName-jét felhasználhatjuk az eszköz megnyitására, majd írás/olvasására.    DeviceNames  : = listUSB(i);    USB_DeviceName := DeviceNames[x].Device;    nyomtatohandle := CreateFile(pchar(USB_DeviceName), GENERIC_READ OR GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);    WriteFile(h, nyomtatohandle, count , b, nil);     CloseHandle(nyomtatohandle);    Olvasni ehhez hasonlóan, ReadFile() tudunk.    Magyar Attila - m.magyar3@chello.hu
usb guid
系統時間:2024-07-03 21:34:45
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!