@@ -45,121 +45,190 @@ Source: "..\ovm.exe"; DestDir: "{app}"; Flags: ignoreversion
4545const
4646 EnvironmentKey = ' Environment' ;
4747
48- function NeedsAddPath (Param: string): boolean;
48+ // Удаляет завершающий обратный слеш из пути, если он есть
49+ function NormalizePath (Path: string): string;
50+ begin
51+ Result := Path;
52+ if (Length(Result) > 0 ) and (Result[Length(Result)] = ' \' ) then
53+ Result := Copy(Result, 1 , Length(Result) - 1 );
54+ end ;
55+
56+ // Проверяет, существует ли путь в переменной PATH
57+ // Учитывает варианты с завершающим слешем и без него
58+ function PathExistsInEnv (Path: string): Boolean;
4959var
50- OrigPath: string;
51- ParamExpanded: string;
60+ EnvPath: string;
61+ NormalizedPath: string;
62+ SearchIn: string;
5263begin
53- ParamExpanded := ExpandConstant(Param);
54- // Normalize: remove trailing backslash
55- if (Length(ParamExpanded) > 0 ) and (ParamExpanded[Length(ParamExpanded)] = ' \' ) then
56- ParamExpanded := Copy(ParamExpanded, 1 , Length(ParamExpanded) - 1 );
64+ Result := False;
65+
66+ // Нормализуем ВХОДНОЙ путь для единообразия
67+ NormalizedPath := NormalizePath(Path);
68+
69+ // Получаем PATH из реестра (НЕ нормализуем — там могут быть пути с backslash)
70+ if not RegQueryStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , EnvPath) then
71+ exit;
72+
73+ // Добавляем разделители по краям для корректного поиска подстроки
74+ SearchIn := ' ;' + Uppercase(EnvPath) + ' ;' ;
75+
76+ // Ищем путь в EnvPath в двух вариантах:
77+ // 1. Без trailing backslash (C:\MyApp)
78+ // 2. С trailing backslash (C:\MyApp\) — на случай, если так записано в реестре
79+ if Pos(' ;' + Uppercase(NormalizedPath) + ' ;' , SearchIn) > 0 then
80+ Result := True
81+ else if Pos(' ;' + Uppercase(NormalizedPath) + ' \;' , SearchIn) > 0 then
82+ Result := True;
83+ end ;
5784
58- if not RegQueryStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , OrigPath) then
85+ // Добавляет путь в переменную окружения PATH
86+ // Возвращает True при успешном добавлении
87+ function AddToPath (Path: string): Boolean;
88+ var
89+ EnvPath: string;
90+ NewPath: string;
91+ NormalizedPath: string;
92+ begin
93+ Result := False;
94+ NormalizedPath := NormalizePath(Path);
95+
96+ // Проверяем, есть ли путь уже в PATH
97+ if PathExistsInEnv(NormalizedPath) then
5998 begin
99+ Log(' Путь уже существует в PATH: ' + NormalizedPath);
60100 Result := True;
61101 exit;
62102 end ;
63- // Check if our path already exists in PATH (case insensitive)
64- // Check without trailing backslash
65- Result := Pos(' ;' + Uppercase(ParamExpanded) + ' ;' , ' ;' + Uppercase(OrigPath) + ' ;' ) = 0 ;
66- // Also check with trailing backslash variant
67- if Result = True then
68- Result := Pos(' ;' + Uppercase(ParamExpanded) + ' \' + ' ;' , ' ;' + Uppercase(OrigPath) + ' ;' ) = 0 ;
103+
104+ // Получаем текущее значение PATH
105+ if RegQueryStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , EnvPath) then
106+ begin
107+ // Добавляем разделитель, если PATH не заканчивается на него
108+ if Length(EnvPath) = 0 then
109+ NewPath := NormalizedPath
110+ else if EnvPath[Length(EnvPath)] = ' ;' then
111+ NewPath := EnvPath + NormalizedPath
112+ else
113+ NewPath := EnvPath + ' ;' + NormalizedPath;
114+ end
115+ else
116+ begin
117+ // PATH не существует, создаём новый
118+ NewPath := NormalizedPath;
119+ end ;
120+
121+ // Записываем обновлённый PATH в реестр
122+ if RegWriteStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , NewPath) then
123+ begin
124+ Log(' Добавлено в PATH: ' + NormalizedPath);
125+ Result := True;
126+ end
127+ else
128+ Log(' Ошибка при добавлении в PATH: ' + NormalizedPath);
69129end ;
70130
71- procedure CurStepChanged (CurStep: TSetupStep);
131+ // Удаляет путь из переменной окружения PATH
132+ // Использует TStringList для парсинга и ручную сборку строки для записи,
133+ // чтобы избежать проблемы с кавычками вокруг путей с пробелами
134+ function RemoveFromPath (Path: string): Boolean;
72135var
73- OrigPath : string;
136+ EnvPath : string;
74137 NewPath: string;
75- AppPath: string;
138+ NormalizedPath: string;
139+ PathList: TStringList;
140+ PathItem: string;
141+ NormalizedItem: string;
142+ i: Integer;
143+ Removed: Boolean;
76144begin
77- if CurStep = ssPostInstall then
145+ Result := False;
146+ Removed := False;
147+ NormalizedPath := NormalizePath(Path);
148+
149+ // Получаем текущее значение PATH
150+ if not RegQueryStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , EnvPath) then
78151 begin
79- AppPath := ExpandConstant(' {app}' );
80- if NeedsAddPath(AppPath) then
152+ Log(' PATH не найден в реестре' );
153+ exit;
154+ end ;
155+
156+ PathList := TStringList.Create;
157+ try
158+ // Разбираем PATH на элементы
159+ PathList.Delimiter := ' ;' ;
160+ PathList.StrictDelimiter := True;
161+ PathList.DelimitedText := EnvPath;
162+
163+ // Удаляем наш путь и пустые элементы
164+ for i := PathList.Count - 1 downto 0 do
81165 begin
82- if RegQueryStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , OrigPath) then
166+ PathItem := PathList[i];
167+
168+ // Удаляем пустые элементы (защита от ";;" в PATH)
169+ if Trim(PathItem) = ' ' then
83170 begin
84- // Add semicolon separator if PATH doesn't already end with one
85- if (Length(OrigPath) > 0 ) and (OrigPath[Length(OrigPath)] = ' ;' ) then
86- NewPath := OrigPath + AppPath
87- else
88- NewPath := OrigPath + ' ;' + AppPath;
89-
90- if RegWriteStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , NewPath) then
91- Log(' Added to PATH: ' + AppPath)
92- else
93- Log(' Failed to add to PATH' );
94- end
95- else
171+ PathList.Delete(i);
172+ Continue;
173+ end ;
174+
175+ // Нормализуем для сравнения (убираем завершающий слеш)
176+ NormalizedItem := NormalizePath(PathItem);
177+
178+ // Сравниваем без учёта регистра
179+ if Uppercase(NormalizedItem) = Uppercase(NormalizedPath) then
96180 begin
97- // PATH doesn't exist, create it
98- if RegWriteStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , AppPath) then
99- Log(' Created PATH with: ' + AppPath)
100- else
101- Log(' Failed to create PATH' );
181+ Log(' Удалено из PATH: ' + PathItem);
182+ PathList.Delete(i);
183+ Removed := True;
102184 end ;
185+ end ;
186+
187+ // Собираем строку вручную, чтобы избежать добавления кавычек
188+ // (TStringList.DelimitedText добавляет кавычки к путям с пробелами)
189+ NewPath := ' ' ;
190+ for i := 0 to PathList.Count - 1 do
191+ begin
192+ if i > 0 then
193+ NewPath := NewPath + ' ;' ;
194+ NewPath := NewPath + PathList[i];
195+ end ;
196+
197+ // Записываем обновлённый PATH в реестр
198+ if RegWriteStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , NewPath) then
199+ begin
200+ if Removed then
201+ Log(' PATH успешно обновлён' )
202+ else
203+ Log(' Путь не найден в PATH: ' + NormalizedPath);
204+ Result := True;
103205 end
104206 else
105- Log(' Path already in PATH, skipping' );
207+ Log(' Ошибка при обновлении PATH' );
208+ finally
209+ PathList.Free;
210+ end ;
211+ end ;
212+
213+ procedure CurStepChanged (CurStep: TSetupStep);
214+ var
215+ AppPath: string;
216+ begin
217+ if CurStep = ssPostInstall then
218+ begin
219+ AppPath := ExpandConstant(' {app}' );
220+ AddToPath(AppPath);
106221 end ;
107222end ;
108223
109224procedure CurUninstallStepChanged (CurUninstallStep: TUninstallStep);
110225var
111- OrigPath: string;
112- NewPath: string;
113226 AppPath: string;
114- PathList: TStringList;
115- PathItem: string;
116- i: Integer;
117227begin
118228 if CurUninstallStep = usPostUninstall then
119229 begin
120230 AppPath := ExpandConstant(' {app}' );
121- // Normalize: remove trailing backslash
122- if (Length(AppPath) > 0 ) and (AppPath[Length(AppPath)] = ' \' ) then
123- AppPath := Copy(AppPath, 1 , Length(AppPath) - 1 );
124-
125- if RegQueryStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , OrigPath) then
126- begin
127- PathList := TStringList.Create;
128- try
129- PathList.Delimiter := ' ;' ;
130- PathList.StrictDelimiter := True;
131- PathList.DelimitedText := OrigPath;
132-
133- // Remove our path from the list (both with and without trailing backslash)
134- // Also remove empty entries to avoid ";;" in PATH
135- for i := PathList.Count - 1 downto 0 do
136- begin
137- PathItem := PathList[i];
138-
139- // Remove empty entries
140- if Trim(PathItem) = ' ' then
141- begin
142- PathList.Delete(i);
143- Continue;
144- end ;
145-
146- // Normalize by removing trailing backslash for comparison
147- if (Length(PathItem) > 0 ) and (PathItem[Length(PathItem)] = ' \' ) then
148- PathItem := Copy(PathItem, 1 , Length(PathItem) - 1 );
149-
150- if Uppercase(PathItem) = Uppercase(AppPath) then
151- begin
152- Log(' Removed from PATH: ' + PathList[i]);
153- PathList.Delete(i);
154- end ;
155- end ;
156-
157- NewPath := PathList.DelimitedText;
158- RegWriteStringValue(HKEY_CURRENT_USER, EnvironmentKey, ' Path' , NewPath);
159- finally
160- PathList.Free;
161- end ;
162- end ;
231+ RemoveFromPath(AppPath);
163232 end ;
164233end ;
165234
0 commit comments