2024-08-04 10:25:42 +02:00
|
|
|
unit IDE.FileAssocFunc;
|
2011-10-06 20:53:09 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
Inno Setup
|
2024-12-31 02:51:11 -06:00
|
|
|
Copyright (C) 1997-2024 Jordan Russell
|
2011-10-06 20:53:09 +02:00
|
|
|
Portions by Martijn Laan
|
|
|
|
For conditions of distribution and use, see LICENSE.TXT.
|
|
|
|
|
2020-08-12 19:54:31 +02:00
|
|
|
Compiler IDE's functions for registering/unregistering the .iss file association
|
2011-10-06 20:53:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
2018-07-15 15:54:03 +02:00
|
|
|
function RegisterISSFileAssociation(const AllowInteractive: Boolean; var AllUsers: Boolean): Boolean;
|
2025-01-01 02:43:46 -06:00
|
|
|
procedure UnregisterISSFileAssociation(const Conditional: Boolean);
|
2011-10-06 20:53:09 +02:00
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
uses
|
2024-08-04 19:59:25 +02:00
|
|
|
Windows, SysUtils, PathFunc, ShlObj, Shared.CommonFunc.Vcl, Shared.CommonFunc;
|
2018-07-15 15:54:03 +02:00
|
|
|
|
|
|
|
function GetRootkey: HKEY;
|
|
|
|
begin
|
|
|
|
if IsAdminLoggedOn then
|
|
|
|
Result := HKEY_LOCAL_MACHINE
|
|
|
|
else
|
|
|
|
Result := HKEY_CURRENT_USER;
|
|
|
|
end;
|
|
|
|
|
2025-01-01 02:43:46 -06:00
|
|
|
procedure UnregisterISSFileAssociationDo(const Rootkey: HKEY;
|
|
|
|
const Conditional: Boolean); forward;
|
2011-10-06 20:53:09 +02:00
|
|
|
|
2018-07-15 15:54:03 +02:00
|
|
|
function RegisterISSFileAssociation(const AllowInteractive: Boolean; var AllUsers: Boolean): Boolean;
|
2011-10-06 20:53:09 +02:00
|
|
|
|
2018-07-15 15:54:03 +02:00
|
|
|
procedure SetKeyValue(const Rootkey: HKEY; const Subkey, ValueName: PChar; const Data: String);
|
2011-10-06 20:53:09 +02:00
|
|
|
|
|
|
|
procedure Check(const Res: Longint);
|
|
|
|
begin
|
|
|
|
if Res <> ERROR_SUCCESS then
|
|
|
|
raise Exception.CreateFmt('Error creating file association:'#13#10'%d - %s',
|
|
|
|
[Res, Win32ErrorString(Res)]);
|
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
K: HKEY;
|
|
|
|
Disp: DWORD;
|
|
|
|
begin
|
2018-07-15 15:54:03 +02:00
|
|
|
Check(RegCreateKeyExView(rvDefault, Rootkey, Subkey, 0, nil, 0, KEY_SET_VALUE,
|
2011-10-06 20:53:09 +02:00
|
|
|
nil, K, @Disp));
|
|
|
|
try
|
|
|
|
Check(RegSetValueEx(K, ValueName, 0, REG_SZ, PChar(Data), (Length(Data)+1)*SizeOf(Data[1])));
|
|
|
|
finally
|
|
|
|
RegCloseKey(K);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
SelfName: String;
|
2018-07-15 15:54:03 +02:00
|
|
|
Rootkey: HKEY;
|
2011-10-06 20:53:09 +02:00
|
|
|
begin
|
2018-07-15 15:54:03 +02:00
|
|
|
Rootkey := GetRootkey;
|
|
|
|
AllUsers := Rootkey = HKEY_LOCAL_MACHINE;
|
|
|
|
|
|
|
|
Result := AllUsers or not AllowInteractive or
|
|
|
|
(MsgBox('Unable to associate for all users without administrative privileges. Do you want to associate only for yourself instead?',
|
|
|
|
'Associate', mbConfirmation, MB_YESNO) = IDYES);
|
|
|
|
if not Result then
|
|
|
|
Exit;
|
|
|
|
|
2025-01-01 04:22:18 -06:00
|
|
|
{ Remove any cruft left around from an older/newer version }
|
|
|
|
UnregisterISSFileAssociationDo(Rootkey, False);
|
|
|
|
|
2011-10-06 20:53:09 +02:00
|
|
|
SelfName := NewParamStr(0);
|
|
|
|
|
2018-07-15 15:54:03 +02:00
|
|
|
SetKeyValue(Rootkey, 'Software\Classes\.iss', nil, 'InnoSetupScriptFile');
|
|
|
|
SetKeyValue(Rootkey, 'Software\Classes\.iss', 'Content Type', 'text/plain');
|
2025-01-01 04:22:18 -06:00
|
|
|
SetKeyValue(Rootkey, 'Software\Classes\.iss\OpenWithProgids', 'InnoSetupScriptFile', '');
|
2011-10-06 20:53:09 +02:00
|
|
|
|
2018-07-15 15:54:03 +02:00
|
|
|
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile', nil, 'Inno Setup Script');
|
|
|
|
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\DefaultIcon', nil, SelfName + ',1');
|
|
|
|
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\open\command', nil,
|
2011-10-06 20:53:09 +02:00
|
|
|
'"' + SelfName + '" "%1"');
|
2018-07-15 15:54:03 +02:00
|
|
|
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile', nil, 'Compi&le');
|
|
|
|
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile\command', nil,
|
2011-10-06 20:53:09 +02:00
|
|
|
'"' + SelfName + '" /cc "%1"');
|
|
|
|
|
2018-07-15 15:54:03 +02:00
|
|
|
{ If we just associated for all users, remove our existing association for the current user if it exists. }
|
|
|
|
if AllUsers then
|
2025-01-01 02:43:46 -06:00
|
|
|
UnregisterISSFileAssociationDo(HKEY_CURRENT_USER, False);
|
2018-07-15 15:54:03 +02:00
|
|
|
|
2011-10-06 20:53:09 +02:00
|
|
|
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
|
|
|
|
end;
|
|
|
|
|
2025-01-01 02:43:46 -06:00
|
|
|
procedure UnregisterISSFileAssociationDo(const Rootkey: HKEY;
|
|
|
|
const Conditional: Boolean);
|
|
|
|
{ If Conditional is True, no action is taken if the association exists but
|
|
|
|
doesn't point to the currently-running EXE file. That can happen when there
|
|
|
|
are multiple Inno Setup installations in different paths. When one of them
|
|
|
|
is uninstalled, the association shouldn't be unregistered if a different
|
|
|
|
installation currently "owns" it. }
|
|
|
|
|
|
|
|
function GetKeyValue(const Rootkey: HKEY; const Subkey: PChar;
|
|
|
|
var Data: String): Boolean;
|
|
|
|
var
|
|
|
|
K: HKEY;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
if RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
|
|
|
|
if RegQueryStringValue(K, nil, Data) then
|
|
|
|
Result := True;
|
|
|
|
RegCloseKey(K);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2025-01-01 04:22:18 -06:00
|
|
|
procedure DeleteValue(const Rootkey: HKEY; const Subkey, ValueName: PChar);
|
|
|
|
var
|
|
|
|
K: HKEY;
|
|
|
|
begin
|
|
|
|
if RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
|
|
|
|
RegDeleteValue(K, ValueName);
|
|
|
|
RegCloseKey(K);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2011-10-06 20:53:09 +02:00
|
|
|
begin
|
2025-01-01 02:43:46 -06:00
|
|
|
if Conditional then begin
|
|
|
|
const ExpectedCommand = '"' + NewParamStr(0) + '" "%1"';
|
|
|
|
var CurCommand: String;
|
|
|
|
if GetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\open\command', CurCommand) and
|
|
|
|
(PathCompare(CurCommand, ExpectedCommand) <> 0) then
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
2024-12-31 05:13:22 -06:00
|
|
|
{ Remove 'InnoSetupScriptFile' entirely. We own it. }
|
|
|
|
RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey,
|
|
|
|
'Software\Classes\InnoSetupScriptFile');
|
2011-10-06 20:53:09 +02:00
|
|
|
|
2025-01-01 04:22:18 -06:00
|
|
|
{ As for '.iss', remove only our OpenWithProgids value, not the whole key.
|
|
|
|
Other apps may have added their own OpenWithProgids values there, and
|
|
|
|
Microsoft docs recommend against trying to delete the key's default value
|
|
|
|
(which points to a ProgID). See:
|
2024-12-31 05:13:22 -06:00
|
|
|
https://learn.microsoft.com/en-us/windows/win32/shell/fa-file-types
|
|
|
|
}
|
2025-01-01 04:22:18 -06:00
|
|
|
DeleteValue(Rootkey, 'Software\Classes\.iss\OpenWithProgids',
|
|
|
|
'InnoSetupScriptFile');
|
2011-10-06 20:53:09 +02:00
|
|
|
|
2024-12-31 02:51:11 -06:00
|
|
|
{ Remove unnecessary key set by previous versions }
|
|
|
|
RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey,
|
|
|
|
'Software\Classes\Applications\Compil32.exe');
|
2018-07-15 15:54:03 +02:00
|
|
|
end;
|
|
|
|
|
2025-01-01 02:43:46 -06:00
|
|
|
procedure UnregisterISSFileAssociation(const Conditional: Boolean);
|
2018-07-15 15:54:03 +02:00
|
|
|
begin
|
2025-01-01 02:43:46 -06:00
|
|
|
UnregisterISSFileAssociationDo(HKEY_CURRENT_USER, Conditional);
|
2024-12-31 05:13:22 -06:00
|
|
|
if IsAdminLoggedOn then
|
2025-01-01 02:43:46 -06:00
|
|
|
UnregisterISSFileAssociationDo(HKEY_LOCAL_MACHINE, Conditional);
|
2024-12-31 05:13:22 -06:00
|
|
|
|
|
|
|
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
|
2011-10-06 20:53:09 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|