| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- unit CompFileAssoc;
- {
- Inno Setup
- Copyright (C) 1997-2020 Jordan Russell
- Portions by Martijn Laan
- For conditions of distribution and use, see LICENSE.TXT.
- Compiler IDE's functions for registering/unregistering the .iss file association
- }
- interface
- function RegisterISSFileAssociation(const AllowInteractive: Boolean; var AllUsers: Boolean): Boolean;
- procedure UnregisterISSFileAssociation;
- implementation
- uses
- Windows, SysUtils, PathFunc, ShlObj, CmnFunc, CmnFunc2;
-
- function GetRootkey: HKEY;
- begin
- if IsAdminLoggedOn then
- Result := HKEY_LOCAL_MACHINE
- else
- Result := HKEY_CURRENT_USER;
- end;
- procedure UnregisterISSFileAssociationDo(const Rootkey: HKEY; const ChangeNotify: Boolean); forward;
- function RegisterISSFileAssociation(const AllowInteractive: Boolean; var AllUsers: Boolean): Boolean;
- procedure SetKeyValue(const Rootkey: HKEY; const Subkey, ValueName: PChar; const Data: String);
- 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
- Check(RegCreateKeyExView(rvDefault, Rootkey, Subkey, 0, nil, 0, KEY_SET_VALUE,
- 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;
- Rootkey: HKEY;
- begin
- 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;
- SelfName := NewParamStr(0);
- SetKeyValue(Rootkey, 'Software\Classes\.iss', nil, 'InnoSetupScriptFile');
- SetKeyValue(Rootkey, 'Software\Classes\.iss', 'Content Type', 'text/plain');
- 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,
- '"' + SelfName + '" "%1"');
- SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\OpenWithInnoSetup', nil,
- 'Open with &Inno Setup');
- SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\OpenWithInnoSetup\command', nil,
- '"' + SelfName + '" "%1"');
- SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile', nil, 'Compi&le');
- SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile\command', nil,
- '"' + SelfName + '" /cc "%1"');
- SetKeyValue(Rootkey, PChar('Software\Classes\Applications\' + PathExtractName(SelfName) + '\SupportedTypes'), '.iss', '');
- { If we just associated for all users, remove our existing association for the current user if it exists. }
- if AllUsers then
- UnregisterISSFileAssociationDo(HKEY_CURRENT_USER, False);
- SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
- end;
- procedure UnregisterISSFileAssociationDo(const Rootkey: HKEY; const ChangeNotify: Boolean);
- function KeyValueEquals(const Rootkey: HKEY; const Subkey: PChar; const Data: String): Boolean;
- var
- K: HKEY;
- S: String;
- begin
- Result := False;
- if RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
- if RegQueryStringValue(K, nil, S) and (PathCompare(Data, S) = 0) then
- Result := True;
- RegCloseKey(K);
- end;
- end;
- function KeyExists(const Rootkey: HKEY; const Subkey: PChar): Boolean;
- var
- K: HKEY;
- begin
- Result := (RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_QUERY_VALUE,
- K) = ERROR_SUCCESS);
- if Result then
- RegCloseKey(K);
- end;
- function GetKeyNumSubkeysValues(const Rootkey: HKEY; const Subkey: PChar;
- var NumSubkeys, NumValues: DWORD): Boolean;
- var
- K: HKEY;
- begin
- Result := False;
- if RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
- Result := RegQueryInfoKey(K, nil, nil, nil, @NumSubkeys, nil, nil,
- @NumValues, nil, nil, nil, nil) = ERROR_SUCCESS;
- RegCloseKey(K);
- end;
- end;
- 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;
- var
- SelfName: String;
- NumSubkeys, NumValues: DWORD;
- begin
- if not KeyExists(Rootkey, 'Software\Classes\InnoSetupScriptFile') and not KeyExists(Rootkey, 'Software\Classes\.iss') then
- Exit;
- SelfName := NewParamStr(0);
- { NOTE: We can't just blindly delete the entire .iss & InnoSetupScriptFile
- keys, otherwise we'd remove the association even if we weren't the one who
- registered it in the first place. }
- { Clean up 'InnoSetupScriptFile' }
- if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile\DefaultIcon', SelfName + ',1') then
- RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\DefaultIcon');
- if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\open\command', '"' + SelfName + '" "%1"') then
- RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\open');
- if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\OpenWithInnoSetup\command', '"' + SelfName + '" "%1"') then
- RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\OpenWithInnoSetup');
- if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile\command', '"' + SelfName + '" /cc "%1"') then
- RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile');
- RegDeleteKeyIfEmpty(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\shell');
- if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile', 'Inno Setup Script') and
- GetKeyNumSubkeysValues(Rootkey, 'Software\Classes\InnoSetupScriptFile', NumSubkeys, NumValues) and
- (NumSubkeys = 0) and (NumValues <= 1) then
- RegDeleteKey(Rootkey, 'Software\Classes\InnoSetupScriptFile');
- { Clean up '.iss' }
- if not KeyExists(Rootkey, 'Software\Classes\InnoSetupScriptFile') and
- KeyValueEquals(Rootkey, 'Software\Classes\.iss', 'InnoSetupScriptFile') then begin
- DeleteValue(Rootkey, 'Software\Classes\.iss', nil);
- DeleteValue(Rootkey, 'Software\Classes\.iss', 'Content Type');
- end;
- RegDeleteKeyIfEmpty(rvDefault, RootKey, 'Software\Classes\.iss');
- if ChangeNotify then
- SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
- end;
- procedure UnregisterISSFileAssociation;
- begin
- UnregisterISSFileAssociationDo(GetRootkey, True);
- end;
- end.
|