InnoSetup,扩展环境变量(从注册表值使用{reg:...}获取)

3
我尝试从注册表中设置默认安装路径:
DefaultDirName={reg:HKCU\Software\Microsoft\VisualStudio\14.0,VisualStudioLocation|{userdocs}\Visual Studio 2015}

我期望得到的目录路径是注册表值数据,这是一种REG_EXPAND_SZ类型的值,然后我需要扩展它的变量,在我的情况下,reg值指向与我设置的默认值相同的路径,一旦InnoSetup在运行时扩展了{userdocs}常量,应该是这样的:

C:\ Users \ Administrator \ Documents \ Visual Studio 2015

但我得到的目录路径不是这样的:

C:\Users\Administrator\Desktop\%USERPROFILE%\Documents\Visual Studio 2015

enter image description here

我从路径 "C:\Users\Administrator\Desktop" 执行安装程序,似乎发生了两件事情,第一是注册表值的路径被追加,第二当然是 %USERPROFILE% 变量没有被展开。
我该如何正确地执行这个操作?
2个回答

4

这是我对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;

你说得对,我的回答没有解决问题,事实上,它甚至让情况变得更糟。我一直想改正它,但我只是没有时间。你发布的解决方案与我为自己编写的非常相似。 - PLopes

1
我在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\14.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;

1
缓冲区长度存在一些主要问题,导致末尾出现随机字符。 - Tobias81
如果需要,请使用@Tobias81的答案(https://dev59.com/IY7da4cB1Zd3GeqP8x6r#34069631),它可以解决这个问题。 - Martin Prikryl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接