2012-02-14 8 views
6

È necessario ottenere il numero di serie del volume per una lettera di unità durante un'installazione creata con Inno Setup. So che le funzioni DLL possono essere importate in Inno, ma sono abbastanza nuovo ad esso e ho alcuni problemi a farlo funzionare. So che la funzione GetVolumeInformation in kernel32 può fare ciò di cui ho bisogno. Qualcuno potrebbe mostrarmi come importare e usare quella funzionalità in uno script Inno per recuperare il numero di serie del volume?Come posso utilizzare GetVolumeInformation in Inno Setup?

Grazie!

risposta

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; 

Testato con Inno- setup versione 5.2.3
Nelle versioni Unicode di Inno-installazione sostituire PChar con PAnsiChar

+0

Grazie ancora e ancora. Perdonami per essere un idiota, ma come lo interpreto? Ad esempio, il mio C drive è etichettato come 449D-0C30 al prompt dei comandi, ma quando eseguo il codice Inno il msgbox mostra 17565-3120. So di essere sulla strada giusta, ma sono nuovo nell'importare funzioni in Inno! Grazie mille per il vostro aiuto! – user1208402

+0

17565-3120 in decimale esadecimale è 449D-0C30. vedi la mia modifica. – kobik

+0

Ho avuto molte persone che danno un solido consiglio. Sono nuovo lo stack, quindi come posso dare loro credito per i loro contributi? – user1208402

4

Poiché lo InnoSetup non supporta i puntatori, è necessario creare la libreria esterna per la chiamata della funzione GetVolumeInformation. I seguenti esempi di codice dovrebbero funzionare per tutte le combinazioni di Delphi e InnoSetup (dal punto di vista del supporto Unicode).

Ecco il codice della libreria 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. 

Ed ecco il codice InnoSetup: Codice

[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

Avevo provato cose molto simili a quelle, infatti ho guardato lo stesso articolo delphi cercando di farlo funzionare. Ma continuo a ricevere errori. Usando il codice che hai fornito, ricevo "Unknown type: PDWORD" nella funzione import. Se lo cambio a qualcos'altro, è più lontano finché non ottengo "Unknown Identifier VolumeSerialNumber" quando raggiunge @VolumeSerialNumber. Ho provato a rimuovere il '@' solo per vedere cosa succede, e compila fino alla chiamata a GetVolumeInformation() e ricevo un errore di "mancata corrispondenza del tipo" al termine della chiamata alla funzione. qualche idea? – user1208402

+1

@TLama, è possibile passare variabile per riferimento ("puntatori"). è sufficiente dichiarare i parametri come 'var lpVolumeSerialNumber: DWORD' ecc. NON è necessario specificare' @ 'nel chiamante. Un altro problema è passare 'nil' alla funzione. questo può essere fatto creando una variabile 'PChar' come' _NIL' e assegnando '# 0 'ad essa. 'HiWord' e' LoWord' sono semplici macro. Sono rimasto bloccato con 'IntToHex' :), ma sono riuscito a implementare il codice iniziale in Inno e ottenere il numero di serie. MA, penso che la tua soluzione finale per mantenere le funzioni di supporto in una DLL separata sia molto meglio! +1 – kobik

+0

Sembra che le nuove versioni di Inno supportino 'IntToHex', ma è anche facile da implementare :) – kobik