2012-02-14 24 views
6

Tôi cần lấy số sê-ri cho một ký tự ổ đĩa trong khi cài đặt được tạo bằng Cài đặt Inno. Tôi biết rằng chức năng DLL có thể được nhập vào Inno, nhưng tôi khá mới với nó và có một số vấn đề nhận được nó để làm việc. Tôi biết rằng các GetVolumeInformation chức năng trong kernel32 có thể làm những gì tôi cần. Ai đó có thể chỉ cho tôi cách nhập và sử dụng chức năng đó trong tập lệnh Inno để truy xuất số sêri khối lượng không?Làm cách nào tôi có thể sử dụng GetVolumeInformation trong Cài đặt Inno?

Cảm ơn!

Trả lời

7

InnoSetup ::

[Code] 
function GetVolumeInformation(
    lpRootPathName: PChar; 
    lpVolumeNameBuffer: PChar; 
    nVolumeNameSize: DWORD; 
    var lpVolumeSerialNumber: DWORD; 
    var lpMaximumComponentLength: DWORD; 
    var lpFileSystemFlags: DWORD; 
    lpFileSystemNameBuffer: PChar; 
    nFileSystemNameSize: DWORD 
): BOOL; 
    external '[email protected] stdcall'; 


function LoWord(dw: DWORD): WORD; 
begin 
    Result := WORD(dw); 
end; 

function HiWord(dw: DWORD): WORD; 
begin 
    Result := WORD((dw shr 16) and $FFFF); 
end; 

function WordToHex(w: WORD): string; 
begin 
    Result := Format('%.4x', [w]); 
end; 

function FindVolumeSerial(const Drive: string): string; 
var 
    FileSystemFlags: DWORD; 
    VolumeSerialNumber: DWORD; 
    MaximumComponentLength: DWORD; 
begin 
    Result := ''; 
    // Note on passing PChars using RemObjects Pascal Script: 
    // '' pass a nil PChar 
    // #0 pass an empty PChar  
    if GetVolumeInformation(
    PChar(Drive), 
    '', // nil 
    0, 
    VolumeSerialNumber, 
    MaximumComponentLength, 
    FileSystemFlags, 
    '', // nil 
    0) 
    then 
    Result := WordToHex(HiWord(VolumeSerialNumber)) + '-' + WordToHex(LoWord(VolumeSerialNumber)); 
end; 

function InitializeSetup(): Boolean; 
begin 
    MsgBox(FindVolumeSerial('c:\'), mbInformation, mb_Ok); 
end; 

Thử nghiệm với Inno- phiên bản thiết lập 5.2.3
Trong các phiên bản Unicode của Inno-Setup thay thế PChar bằng PAnsiChar

+0

Cảm ơn bạn nhiều lần. Tha thứ cho tôi vì là một thằng ngốc, nhưng làm thế nào để tôi giải thích điều đó? Ví dụ, ổ đĩa C của tôi được gắn nhãn là 449D-0C30 tại dấu nhắc lệnh, nhưng khi tôi chạy mã Inno của bạn, hộp thư hiển thị 17565-3120. Tôi biết tôi đang đi đúng hướng, nhưng tôi mới nhập chức năng vào Inno! Cảm ơn rất nhiều vì sự giúp đỡ của bạn! – user1208402

+0

17565-3120 trong thập phân thập phân là 449D-0C30. xem chỉnh sửa của tôi. – kobik

+0

Tôi đã có nhiều người cho vay lời khuyên chắc chắn. Tôi mới là ngăn xếp, vậy làm thế nào tôi có thể cho họ tín dụng cho những đóng góp của họ? – user1208402

4

InnoSetup không hỗ trợ con trỏ, bạn sẽ phải tạo thư viện bên ngoài để gọi hàm GetVolumeInformation. Các mẫu mã sau đây sẽ làm việc cho tất cả các kết hợp của Delphi và InnoSetup (từ điểm hỗ trợ Unicode).

Dưới đây là mã thư viện Delphi:

library VolumeInformation; 

uses 
    Types, Classes, SysUtils, Windows; 

var 
    SerialNumber: AnsiString; 

function GetVolumeSerial(Drive: PAnsiChar): PAnsiChar; stdcall; 
var 
    FileSystemFlags: DWORD; 
    VolumeSerialNumber: DWORD; 
    MaximumComponentLength: DWORD; 
begin 
    SerialNumber := ''; 
    GetVolumeInformationA(Drive, nil, 0, @VolumeSerialNumber, 
    MaximumComponentLength, FileSystemFlags, nil, 0); 
    SerialNumber := IntToHex(HiWord(VolumeSerialNumber), 4) + ' - ' + 
    IntToHex(LoWord(VolumeSerialNumber), 4); 
    Result := PAnsiChar(SerialNumber); 
end; 

exports 
    GetVolumeSerial; 

end. 

Và đây là mã InnoSetup: Mã

[Files] 
Source: "VolumeInformation.dll"; Flags: dontcopy 

[Code] 

function GetVolumeSerial(Drive: PAnsiChar): PAnsiChar; 
    external '[email protected]:VolumeInformation.dll stdcall setuponly'; 

procedure ButtonOnClick(Sender: TObject); 
var 
    S: string; 
begin 
    S := GetVolumeSerial('c:\'); 
    MsgBox(S, mbInformation, mb_Ok); 
end; 
+0

Tôi đã thử mọi thứ rất giống với những thứ đó, trên thực tế tôi đã xem bài viết delphi đó đang cố gắng làm cho nó hoạt động. Nhưng tôi vẫn gặp lỗi. Sử dụng mã bạn đã cung cấp, tôi nhận được "Loại không xác định: PDWORD" trong chức năng nhập. Nếu tôi thay đổi nó thành cái gì đó khác, nó tuân thủ xa hơn cho đến khi tôi nhận được "Unknown identifier VolumeSerialNumber" khi nó đạt đến @VolumeSerialNumber. Tôi đã thử gỡ bỏ '@' chỉ để xem điều gì xảy ra, và nó biên dịch tất cả các cách để gọi đến GetVolumeInformation() và tôi nhận được lỗi "loại không phù hợp" ở cuối cuộc gọi hàm. Có suy nghĩ gì không? – user1208402

+1

@TLama, Bạn có thể chuyển biến theo tham chiếu ("con trỏ"). bạn chỉ cần khai báo các tham số dưới dạng 'var lpVolumeSerialNumber: DWORD' vv. KHÔNG cần chỉ rõ' @ 'trong người gọi. Một vấn đề khác là chuyển 'nil' sang hàm. điều này có thể được thực hiện bằng cách gán một biến 'PChar' như' _NIL' và gán '# 0' cho nó. 'HiWord' và' LoWord' là các macro đơn giản. Tôi đã bị mắc kẹt với 'IntToHex' :) nhưng tôi đã có thể thực hiện mã ban đầu của bạn bên trong Inno và nhận được số sê-ri. NHƯNG, tôi nghĩ rằng giải pháp cuối cùng của bạn để giữ chức năng trợ giúp trong một DLL riêng biệt là tốt hơn nhiều! +1 – kobik

+0

Có vẻ như phiên bản mới hơn của Inno hỗ trợ 'IntToHex', nhưng nó cũng dễ thực hiện :) – kobik