I try to set the default install path from the registry:
DefaultDirName={reg:HKCU\\Software\\Microsoft\\VisualStudio\\14.0,VisualStudioLocation|{userdocs}\\Visua
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;
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;