InnoSetup, expand environment variable (taken from registry value using {reg:…} )

房东的猫 提交于 2019-12-01 21:13:37

I cannot find any use of the ExpandEnvironmentStrings function in Inno Setup source which points to a fact (and correct me if I am wrong), that Inno Setup cannot expand such path (there is no function, nor constant for that), or there's a different API function that I'm not aware of. Of course file names like that are supported in Inno Setup because they're passed to the system functions that can internally expand them. There just seems to be no function or constant that could do it in script. My suggestion is a hack like this:

[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;
Tobias81

Here is my improved version of ElektroStudios' solution:

It takes care of correct string-termination and does not rely on the 0-termination added by the Win32-function (guess it's not good to use that in Pascal code).

[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;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!