InnoSetup,扩展环境变量(使用 {reg:...} 从注册表值中获取)
InnoSetup, expand environment variable (taken from registry value using {reg:...} )
我尝试从注册表设置默认安装路径:
DefaultDirName={reg:HKCU\Software\Microsoft\VisualStudio.0,VisualStudioLocation|{userdocs}\Visual Studio 2015}
我希望得到的目录路径是注册表值数据,是一个REG_EXPAND_SZ
类型的值,那么我需要展开它的变量,我的例子中的reg值指向与我设置的默认值相同的路径,一旦 {userdocs}
常量在运行时被 InnoSetup 扩展,应该是这样的:
C:\Users\Administrator\Documents\Visual Studio 2015
但是我没有得到它作为目录路径:
C:\Users\Administrator\Desktop\%USERPROFILE%\Documents\Visual Studio
2015
我从“C:\Users\Administrator\Desktop”路径执行安装程序,所以这里似乎发生了两件事,第一是注册表值的路径是只是附加,第二个当然是 %USERPROFILE%
变量没有展开。
我怎样才能正确地做到这一点?
我在 Inno Setup 源代码中找不到 ExpandEnvironmentStrings
函数的任何用法,它指向一个事实(如果我错了请纠正我),即 Inno Setup 无法扩展这样的路径(没有函数,也不是常量),或者有一个我不知道的不同的 API 函数。当然 Inno Setup 支持这样的文件名,因为它们被传递给可以在内部扩展它们的系统函数。似乎没有函数或常量可以在脚本中完成。我的建议是像这样 hack:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={code:GetDefaultDirName}
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
const
RegKeyVS2015 = 'Software\Microsoft\VisualStudio.0';
function ExpandEnvironmentStrings(lpSrc: string; lpDst: string; nSize: DWORD): DWORD;
external 'ExpandEnvironmentStrings{#AW}@kernel32.dll stdcall';
function ExpandEnvVars(const Input: string): string;
var
BufSize: DWORD;
begin
BufSize := ExpandEnvironmentStrings(Input, #0, 0);
if BufSize > 0 then
begin
SetLength(Result, BufSize);
if ExpandEnvironmentStrings(Input, Result, Length(Result)) = 0 then
RaiseException(Format('Expanding env. strings failed. %s', [
SysErrorMessage(DLLGetLastError)]));
end
else
RaiseException(Format('Expanding env. strings failed. %s', [
SysErrorMessage(DLLGetLastError)]));
end;
function GetDefaultDirName(Param: string): string;
begin
if RegQueryStringValue(HKCU, RegKeyVS2015, 'VisualStudioLocation', Result) then
Result := ExpandEnvVars(Result)
else
Result := ExpandConstant('{userdocs}\Visual Studio 2015');
end;
以下是我对 ElektroStudios 解决方案的改进版本:
它负责正确的字符串终止,而不依赖于 Win32 函数添加的 0 终止(我猜在 Pascal 代码中使用它并不好)。
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function ExpandEnvironmentStrings(lpSrc: String; lpDst: String; nSize: DWORD): DWORD;
external 'ExpandEnvironmentStrings{#AW}@kernel32.dll stdcall';
function ExpandEnvVars(const Input: String): String;
var
Buf: String;
BufSize: DWORD;
begin
BufSize := ExpandEnvironmentStrings(Input, #0, 0);
if BufSize > 0 then
begin
SetLength(Buf, BufSize); // The internal representation is probably +1 (0-termination)
if ExpandEnvironmentStrings(Input, Buf, BufSize) = 0 then
RaiseException(Format('Expanding env. strings failed. %s', [SysErrorMessage(DLLGetLastError)]));
#if AW == "A"
Result := Copy(Buf, 1, BufSize - 2);
#else
Result := Copy(Buf, 1, BufSize - 1);
#endif
end
else
RaiseException(Format('Expanding env. strings failed. %s', [SysErrorMessage(DLLGetLastError)]));
end;
我尝试从注册表设置默认安装路径:
DefaultDirName={reg:HKCU\Software\Microsoft\VisualStudio.0,VisualStudioLocation|{userdocs}\Visual Studio 2015}
我希望得到的目录路径是注册表值数据,是一个REG_EXPAND_SZ
类型的值,那么我需要展开它的变量,我的例子中的reg值指向与我设置的默认值相同的路径,一旦 {userdocs}
常量在运行时被 InnoSetup 扩展,应该是这样的:
C:\Users\Administrator\Documents\Visual Studio 2015
但是我没有得到它作为目录路径:
C:\Users\Administrator\Desktop\%USERPROFILE%\Documents\Visual Studio 2015
我从“C:\Users\Administrator\Desktop”路径执行安装程序,所以这里似乎发生了两件事,第一是注册表值的路径是只是附加,第二个当然是 %USERPROFILE%
变量没有展开。
我怎样才能正确地做到这一点?
我在 Inno Setup 源代码中找不到 ExpandEnvironmentStrings
函数的任何用法,它指向一个事实(如果我错了请纠正我),即 Inno Setup 无法扩展这样的路径(没有函数,也不是常量),或者有一个我不知道的不同的 API 函数。当然 Inno Setup 支持这样的文件名,因为它们被传递给可以在内部扩展它们的系统函数。似乎没有函数或常量可以在脚本中完成。我的建议是像这样 hack:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={code:GetDefaultDirName}
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
const
RegKeyVS2015 = 'Software\Microsoft\VisualStudio.0';
function ExpandEnvironmentStrings(lpSrc: string; lpDst: string; nSize: DWORD): DWORD;
external 'ExpandEnvironmentStrings{#AW}@kernel32.dll stdcall';
function ExpandEnvVars(const Input: string): string;
var
BufSize: DWORD;
begin
BufSize := ExpandEnvironmentStrings(Input, #0, 0);
if BufSize > 0 then
begin
SetLength(Result, BufSize);
if ExpandEnvironmentStrings(Input, Result, Length(Result)) = 0 then
RaiseException(Format('Expanding env. strings failed. %s', [
SysErrorMessage(DLLGetLastError)]));
end
else
RaiseException(Format('Expanding env. strings failed. %s', [
SysErrorMessage(DLLGetLastError)]));
end;
function GetDefaultDirName(Param: string): string;
begin
if RegQueryStringValue(HKCU, RegKeyVS2015, 'VisualStudioLocation', Result) then
Result := ExpandEnvVars(Result)
else
Result := ExpandConstant('{userdocs}\Visual Studio 2015');
end;
以下是我对 ElektroStudios 解决方案的改进版本:
它负责正确的字符串终止,而不依赖于 Win32 函数添加的 0 终止(我猜在 Pascal 代码中使用它并不好)。
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function ExpandEnvironmentStrings(lpSrc: String; lpDst: String; nSize: DWORD): DWORD;
external 'ExpandEnvironmentStrings{#AW}@kernel32.dll stdcall';
function ExpandEnvVars(const Input: String): String;
var
Buf: String;
BufSize: DWORD;
begin
BufSize := ExpandEnvironmentStrings(Input, #0, 0);
if BufSize > 0 then
begin
SetLength(Buf, BufSize); // The internal representation is probably +1 (0-termination)
if ExpandEnvironmentStrings(Input, Buf, BufSize) = 0 then
RaiseException(Format('Expanding env. strings failed. %s', [SysErrorMessage(DLLGetLastError)]));
#if AW == "A"
Result := Copy(Buf, 1, BufSize - 2);
#else
Result := Copy(Buf, 1, BufSize - 1);
#endif
end
else
RaiseException(Format('Expanding env. strings failed. %s', [SysErrorMessage(DLLGetLastError)]));
end;