2012-02-14 15 views
6

Necesito obtener el número de serie del volumen para una letra de unidad durante una instalación creada con Inno Setup. Sé que las funciones DLL se pueden importar a Inno, pero soy bastante nuevo y tengo algunos problemas para que funcione. Sé que la función GetVolumeInformation en kernel32 puede hacer lo que necesito. ¿Podría alguien mostrarme cómo importar y usar esa funcionalidad en una secuencia de comandos Inno para recuperar el número de serie del volumen?¿Cómo puedo usar GetVolumeInformation en Inno Setup?

Gracias!

Respuesta

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; 

probado con Inno configuración versión 5.2.3
En versiones Unicode de Inno-Setup, reemplace PChar con PAnsiChar

+0

Gracias una y otra vez. Perdóname por ser un idiota, pero ¿cómo interpreto eso? Por ejemplo, mi unidad C está etiquetada como 449D-0C30 en el símbolo del sistema, pero cuando ejecuto su código Inno el msgbox muestra 17565-3120. Sé que estoy en el camino correcto, pero soy nuevo en la importación de funciones en Inno! ¡Muchas gracias por tu ayuda! – user1208402

+0

17565-3120 en decimal hexadecimal es 449D-0C30. ver mi edición – kobik

+0

He tenido varias personas que prestan sólidos consejos. Soy nuevo en la pila, entonces, ¿cómo puedo darles crédito por sus contribuciones? – user1208402

4

Como el InnoSetup no es compatible con los punteros, deberá crear la biblioteca externa para la llamada de la función GetVolumeInformation. Los siguientes ejemplos de código deberían funcionar para todas las combinaciones de Delphi e InnoSetup (desde el punto de vista de soporte Unicode).

Aquí está el código de la biblioteca 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. 

Y aquí está el código InnoSetup: Código

[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

Había intentado cosas muy similares a esas, de hecho, miré ese mismo artículo delphi tratando de ponerlo a funcionar. Pero sigo recibiendo errores. Usando el código que proporcionó, obtengo "Tipo desconocido: PDWORD" en la función de importación. Si cambio eso a otra cosa, se cumple más hasta que obtengo "Identificador desconocido VolumeSerialNumber" cuando alcanza @VolumeSerialNumber. Traté de eliminar el '@' solo para ver qué pasa, y compila todo el camino hasta la llamada a GetVolumeInformation() y recibo un error de "tipo no coinciden" al final de la llamada a la función. ¿Alguna idea? – user1208402

+1

@TLama, puede pasar variables por referencia ("punteros"). simplemente necesita declarar los parámetros como 'var lpVolumeSerialNumber: DWORD', etc. NO es necesario especificar' @ 'en la persona que llama. Otro problema es pasar 'nil' a la función. esto se puede hacer encapsulando una variable 'PChar' como' _NIL' y asignándole '# 0'. 'HiWord' y' LoWord' son macros simples. Me quedé atrapado con 'IntToHex' :) pero pude implementar tu código inicial dentro de Inno y obtener el número de serie. PERO, creo que su solución final para mantener las funciones de ayuda en una DLL separada es mucho mejor. +1 – kobik

+0

Parece que las versiones más recientes de Inno admiten 'IntToHex', pero también es fácil de implementar :) – kobik

Cuestiones relacionadas