3

我嘗試設置默認從註冊表安裝路徑:InnoSetup,擴大環境變量(使用{REG:...}從註冊表值取)

DefaultDirName={reg:HKCU\Software\Microsoft\VisualStudio\14.0,VisualStudioLocation|{userdocs}\Visual Studio 2015} 

,我希望獲得的目錄路徑註冊表值數據,這是REG_EXPAND_SZ類型的值,那麼我需要擴展它的變量,在我的情況下,reg值指向與我設置的默認值相同的路徑,一旦{userdocs}常量被擴展爲運行時間由InnoSetup,應該是這樣的:

C:\用戶\管理\文檔\ Visual Studio的2015年

的而是說我得到這個爲目錄路徑:

C:\用戶\管理員\桌面\%USERPROFILE%\文件\ Visual Studio的 2015年

enter image description here

我執行從「C中的安裝:\使用rs \ Administrator \ Desktop「的路徑,所以這裏似乎發生了兩件事情,第一個是註冊表值的路徑剛剛追加,第二個是當然%USERPROFILE%變量沒有擴展。

我該如何正確地做到這一點?

回答

1

我找不到任何使用Inno Setup源代碼中的ExpandEnvironmentStrings函數,它指向一個事實(並糾正我,如果我錯了),Inno安裝程序無法擴展這樣的路徑(沒有函數,也不是常數) ,或者有一個我不知道的API函數。當然,Inno Setup支持這樣的文件名,因爲它們被傳遞給可以在內部擴展它們的系統函數。似乎沒有任何功能或常量可以在腳本中實現。我的建議是破解這樣的:

[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

+0

確實,使用[回答@ Tobias81](http://stackoverflow.com/a/34069631/850848)修復了這個問題。 –

4

這裏是我的ElektroStudios的解決方案的改進版本:

它負責正確的字符串終止的,不依賴於添加的0終止Win32函數(猜測在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; 
+0

你說得對,我的回答並沒有解決問題,事實上,它甚至是最糟糕的。我一直想要改變它,但我沒有時間。您發佈的解決方案與我爲自己寫的內容非常相似。 – PLopes