2010-07-21 13 views
54

Inno Setup pozwala ustawić zmienne środowiskowe za pośrednictwem sekcji [Rejestr] (ustawiając klucz rejestru, który odpowiada zmiennej środowiskowej)Jak zmodyfikować zmienną środowiskową PATH podczas uruchamiania instalatora Inno Setup?

Czasami jednak nie wystarczy ustawić zmienną środowiskową. Często chcesz go zmodyfikować. Na przykład: po instalacji możesz chcieć dodać/usunąć katalog do/ze zmiennej środowiskowej PATH.

Jak zmodyfikować zmienną środowiskową PATH z poziomu InnoSetup?

Odpowiedz

71

Ścieżka w podanym kluczu rejestru ma wartość typu REG_EXPAND_SZ. Jak dokumentacji Inno Setup dla [Registry] stanach sekcja istnieje sposób, aby dołączyć elementy do tych:

Na string, expandsz lub multisz wartości typu, można użyć specjalnego stałej nazwie {olddata} w ten parametr. {olddata} zostaje zastąpione poprzednimi danymi wartości rejestru. Stała {olddata} może być przydatna, jeśli chcesz dołączyć ciąg do istniejącej wartości, na przykład {olddata};{app}. Jeśli wartość nie istnieje lub istniejąca wartość nie jest typem łańcucha, stała {olddata} jest cicho usuwana.

Więc dołącz do ścieżki sekcja rejestru podobny do tego mogą być stosowane:

[Registry] 
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \ 
    ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo" 

który dołączy „C: \ foo” katalog na ścieżce.

Niestety zostanie to powtórzone podczas instalacji po raz drugi, co również powinno zostać naprawione. Parametr Check z funkcji zakodowanego w Pascal skrypt może być używany w celu sprawdzenia, czy ścieżka rzeczywiście muszą być rozszerzony:

[Registry] 
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \ 
    ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo"; \ 
    Check: NeedsAddPath('C:\foo') 

Funkcja ta odczytuje oryginalną wartość ścieżki i sprawdza, czy dany katalog jest już w nim zawartych . Aby to zrobić, dodaje i dodaje znaki średnika, które są używane do oddzielania katalogów na ścieżce. W celu uwzględnienia faktu, że poszukiwany katalogu może być pierwszym lub ostatnim elementem średnik znaków są poprzedzany i dołączone do pierwotnej wartości, a także:

[Code] 

function NeedsAddPath(Param: string): boolean; 
var 
    OrigPath: string; 
begin 
    if not RegQueryStringValue(HKEY_LOCAL_MACHINE, 
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 
    'Path', OrigPath) 
    then begin 
    Result := True; 
    exit; 
    end; 
    { look for the path with leading and trailing semicolon } 
    { Pos() returns 0 if not found } 
    Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0; 
end; 

Zauważ, że być może trzeba rozszerzyć stałe, zanim przekaże je jako parametr do funkcji sprawdzania, szczegóły w dokumentacji.

Usunięcie tego katalogu ze ścieżki podczas dezinstalacji można wykonać w podobny sposób i pozostawić jako ćwiczenie dla czytelnika.

+1

Czy nie byłoby wspaniale, gdybyś mógł po prostu przekazać '{olddata } 'do funkcji Check, aby nie trzeba było ponownie odczytywać wartości w kodzie? (może możesz - nie próbowałem);) –

+3

Inną rzeczą jest to, że ścieżka może tam być, ale użyj innego znaku (łatwo naprawić za pomocą funkcji 'UpperCase' lub somesuch) lub, co gorsza, użyj nazw ścieżek 8.3 (np. "C: \ Progra ~ 1 \ MyProg") lub zmiennych środowiskowych (np. "% programfiles% \ MyProg"). Byłoby to koszmarem również do wykrycia tych ... –

+1

a co, kiedy program zostanie odinstalowany? Jak usunąć ścieżkę ze zmiennej środowiskowej PATH? –

6

NeedsAddPath w the answer by @mghie nie sprawdza końcowego \ i wielkości liter. Napraw to.

function NeedsAddPath(Param: string): boolean; 
var 
    OrigPath: string; 
begin 
    if not RegQueryStringValue(
    HKEY_LOCAL_MACHINE, 
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 
    'Path', OrigPath) 
    then begin 
    Result := True; 
    exit; 
    end; 
    { look for the path with leading and trailing semicolon } 
    { Pos() returns 0 if not found } 
    Result := 
    (Pos(';' + UpperCase(Param) + ';', ';' + UpperCase(OrigPath) + ';') = 0) and 
    (Pos(';' + UpperCase(Param) + '\;', ';' + UpperCase(OrigPath) + ';') = 0); 
end; 
+3

Jak używać zmiennej zamiast "C: \ foo"? Próbowałem NeedsAddPath ("{app}"), ale to nie działa - po prostu łącząc ścieżkę, chociaż jest już zakończone. Czy możesz poradzić, proszę? –

+1

Wystarczy, aby odpowiedzieć na powyższy komentarz, może być przydatny dla innych: Musisz użyć funkcji 'ExpandConstant()'. – Jack

+0

Dziękuję Jack. Jednak chciałbym zobaczyć przykład NeedsAddPath ("{app} \ MoreDirectoriesHere"). – vezenkov

14

Możesz użyć funkcji LegRoom.net modpath.iss skrypt w InnoSetup pliku skryptu:

#define MyTitleName "MyApp" 

[Setup] 
ChangesEnvironment=yes 

[CustomMessages] 
AppAddPath=Add application directory to your environmental path (required) 

[Files] 
Source: "install\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; 

[Icons] 
Name: "{group}\{cm:UninstallProgram,{#MyTitleName}}"; Filename: "{uninstallexe}"; Comment: "Uninstalls {#MyTitleName}" 
Name: "{group}\{#MyTitleName}"; Filename: "{app}\{#MyTitleName}.EXE"; WorkingDir: "{app}"; AppUserModelID: "{#MyTitleName}"; Comment: "Runs {#MyTitleName}" 
Name: "{commondesktop}\{#MyTitleName}"; Filename: "{app}\{#MyTitleName}.EXE"; WorkingDir: "{app}"; AppUserModelID: "{#MyTitleName}"; Comment: "Runs {#MyTitleName}" 

[Registry] 
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}" 

[Tasks] 
Name: modifypath; Description:{cm:AppAddPath}; 

[Code] 

const 
    ModPathName = 'modifypath'; 
    ModPathType = 'system'; 

function ModPathDir(): TArrayOfString; 
begin 
    setArrayLength(Result, 1) 
    Result[0] := ExpandConstant('{app}'); 
end; 

#include "modpath.iss" 
1

Tutaj jest kompletnym rozwiązaniem problemu, który ignoruje obudowę, sprawdza istnienie ścieżki kończąc \ a także rozszerza stałe w param:

function NeedsAddPath(Param: string): boolean; 
var 
    OrigPath: string; 
    ParamExpanded: string; 
begin 
    //expand the setup constants like {app} from Param 
    ParamExpanded := ExpandConstant(Param); 
    if not RegQueryStringValue(HKEY_LOCAL_MACHINE, 
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 
    'Path', OrigPath) 
    then begin 
    Result := True; 
    exit; 
    end; 
    // look for the path with leading and trailing semicolon and with or without \ ending 
    // Pos() returns 0 if not found 
    Result := Pos(';' + UpperCase(ParamExpanded) + ';', ';' + UpperCase(OrigPath) + ';') = 0; 
    if Result = True then 
    Result := Pos(';' + UpperCase(ParamExpanded) + '\;', ';' + UpperCase(OrigPath) + ';') = 0; 
end; 
+0

Dość pewny problem: sprawdza tylko przypadek '' \; 'tylko wtedy, gdy znaleziono przypadek ';'. – Stewart

2

Miałem ten sam problem, ale pomimo powyższych odpowiedzi znalazłem rozwiązanie niestandardowe i chciałbym je udostępnić.

Przede wszystkim Utworzyłem plik environment.iss z 2 metod - jedna za dodanie ścieżki do środowiska za Path zmienna i drugi, aby go usunąć:

[Code] 
const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; 

procedure EnvAddPath(Path: string); 
var 
    Paths: string; 
begin 
    { Retrieve current path (use empty string if entry not exists) } 
    if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) 
    then Paths := ''; 

    { Skip if string already found in path } 
    if Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';') > 0 then exit; 

    { App string to the end of the path variable } 
    Paths := Paths + ';'+ Path +';' 

    { Overwrite (or create if missing) path environment variable } 
    if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) 
    then Log(Format('The [%s] added to PATH: [%s]', [Path, Paths])) 
    else Log(Format('Error while adding the [%s] to PATH: [%s]', [Path, Paths])); 
end; 

procedure EnvRemovePath(Path: string); 
var 
    Paths: string; 
    P: Integer; 
begin 
    { Skip if registry entry not exists } 
    if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then 
     exit; 

    { Skip if string not found in path } 
    P := Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';'); 
    if P = 0 then exit; 

    { Update path variable } 
    Delete(Paths, P - 1, Length(Path) + 1); 

    { Overwrite path environment variable } 
    if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) 
    then Log(Format('The [%s] removed from PATH: [%s]', [Path, Paths])) 
    else Log(Format('Error while removing the [%s] from PATH: [%s]', [Path, Paths])); 
end; 

referencyjny: RegQueryStringValue, RegWriteStringValue

Teraz w głównym pliku .iss mogę dołączyć ten plik i odsłuchać 2 zdarzenia (więcej o zdarzeniach, których można się dowiedzieć w sekcji Event Functions w dokumentacji), CurStepChanged, aby dodać ścieżkę po instalacji i CurUninstallStepChanged usunąć go, gdy użytkownik odinstaluje aplikację. W poniższym przykładzie skrypt dodaj/usuń katalog bin (w stosunku do katalogu instalacyjnym):

#include "environment.iss" 

[Setup] 
ChangesEnvironment=true 

; More options in setup section as well as other sections like Files, Components, Tasks... 

[Code] 
procedure CurStepChanged(CurStep: TSetupStep); 
begin 
    if CurStep = ssPostInstall 
    then EnvAddPath(ExpandConstant('{app}') +'\bin'); 
end; 

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); 
begin 
    if CurUninstallStep = usPostUninstall 
    then EnvRemovePath(ExpandConstant('{app}') +'\bin'); 
end; 

referencyjny: ExpandConstant

Uwaga nr 1: Instalacja krok dodać ścieżkę tylko raz (gwarantuje powtarzalność instalacji).

Uwaga # 2: Odinstaluj krok usuń tylko jedno wystąpienie ścieżki ze zmiennej.

Bonus: Krok instalacji z polem wyboru "Dodaj do zmiennej PATH".

Inno Setup - Add to PATH variable

Aby dodać kroku instalacji z wyboru „Dodaj do zmiennej PATH” zdefiniować nowe zadanie w [Tasks] sekcji (domyślnie zaznaczone):

[Tasks] 
Name: envPath; Description: "Add to PATH variable" 

Następnie można sprawdzić w CurStepChanged imprezy :

procedure CurStepChanged(CurStep: TSetupStep); 
begin 
    if (CurStep = ssPostInstall) and IsTaskSelected('envPath') 
    then EnvAddPath(ExpandConstant('{app}') +'\bin'); 
end; 
Powiązane problemy