Winapi 如何在Inno安装程序中使用GetVolumeInformation?
在使用Inno Setup创建的安装过程中,我需要获取驱动器号的卷序列号。我知道DLL函数可以导入Inno,但我对它还比较陌生,在让它工作时遇到了一些问题。我知道内核32中的GetVolumeInformation函数可以满足我的需要。有人能告诉我如何在Inno脚本中导入和使用该功能来检索卷序列号吗 谢谢 由于不支持指针,因此必须为函数调用创建外部库。以下代码示例适用于Delphi和InnoSetup的所有组合(从Unicode支持的角度来看) 以下是Delphi库代码:Winapi 如何在Inno安装程序中使用GetVolumeInformation?,winapi,installation,inno-setup,pascalscript,Winapi,Installation,Inno Setup,Pascalscript,在使用Inno Setup创建的安装过程中,我需要获取驱动器号的卷序列号。我知道DLL函数可以导入Inno,但我对它还比较陌生,在让它工作时遇到了一些问题。我知道内核32中的GetVolumeInformation函数可以满足我的需要。有人能告诉我如何在Inno脚本中导入和使用该功能来检索卷序列号吗 谢谢 由于不支持指针,因此必须为函数调用创建外部库。以下代码示例适用于Delphi和InnoSetup的所有组合(从Unicode支持的角度来看) 以下是Delphi库代码: library Vol
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.
以下是InnoSetup代码:
[Files]
Source: "VolumeInformation.dll"; Flags: dontcopy
[Code]
function GetVolumeSerial(Drive: PAnsiChar): PAnsiChar;
external 'GetVolumeSerial@files:VolumeInformation.dll stdcall setuponly';
procedure ButtonOnClick(Sender: TObject);
var
S: string;
begin
S := GetVolumeSerial('c:\');
MsgBox(S, mbInformation, mb_Ok);
end;
Inno设置代码::
[Code]
function GetVolumeInformation(
lpRootPathName: PChar;
lpVolumeNameBuffer: PChar;
nVolumeNameSize: DWORD;
var lpVolumeSerialNumber: DWORD;
var lpMaximumComponentLength: DWORD;
var lpFileSystemFlags: DWORD;
lpFileSystemNameBuffer: PChar;
nFileSystemNameSize: DWORD
): BOOL;
external 'GetVolumeInformationA@kernel32.dll 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;
使用Inno安装程序版本5.2.3进行测试
在Inno Setup的Unicode版本中将
PChar
替换为PAnsiChar
中,我尝试过与之非常相似的方法,事实上,我看过了同一篇delphi文章,试图让它发挥作用。但我总是出错。使用您提供的代码,我在函数导入中得到“未知类型:PDWORD”。如果我将其更改为其他内容,它将继续执行,直到它达到@VolumeSerialNumber时我得到“未知标识符VolumeSerialNumber”。我试图删除“@”只是为了看看会发生什么,它一直编译到调用GetVolumeInformation(),在函数调用结束时收到一个“类型不匹配”错误。有什么想法吗?@TLama,您可以通过引用(“指针”)传递变量。只需将参数声明为var lpVolumeSerialNumber:DWORD
等。无需在调用者中指定@
。另一个问题是将nil
传递给函数。这可以通过装入PChar
变量(如\u NIL
)并为其赋值\0
来实现HiWord
和LoWord
是简单的宏。我一直使用IntToHex
:),但是我能够在Inno中实现您的初始代码并获得序列号。但是,我认为将助手函数保留在单独的DLL中的最终解决方案要好得多+1看起来像更新版本的Inno支持IntToHex
,但它也很容易实现:)@kobik,关于lpVolumeSerialNumber
声明的观点很好。关于IntToHex
我不确定(即使ReObject的引用也没有提到它)。然而,我认为OP正在进行一些注册过程,因为我不知道获取卷序列号的任何合理原因,所以我认为该库在其他方面也可能有用。但是发布您所拥有的,也许您的解决方案更适合OP;)@TLama感谢您的输入,无需道歉!我总是感激每个人的帮助,即使不是100%正确。至少我们都可以通过这种方式学到一些东西!根据您最新的示例,我仍然对将函数导入Inno感到有些困惑。我是否必须编译DLL来存储Inno的外部函数?或者一个更好的问题是我怎么做?这听起来是一个好主意,供将来参考,但我希望只使用本机Windows DLL进行函数导入。非常感谢你的帮助!再三感谢你。原谅我是个白痴,但我该怎么解释呢?例如,我的C驱动器在命令提示符下标记为449D-0C30,但当我运行您的Inno代码时,msgbox显示为17565-3120。我知道我的思路是正确的,但我对将函数导入Inno还不熟悉!非常感谢你的帮助!我已经有好几个人给了我可靠的建议。我是新来的,我该如何表扬他们的贡献呢?