Search code examples
registryinno-setuppascalscript

Inno Setup iterate through users in Registry to remove entry for each users Run key


I am looking to find a way to iterate through the users in the Registry i.e. the HKEY_USERS branch of the Registry) in order to remove an entry that might have been created by the application in the user's profile under HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run when the software is uninstalled (i.e. in the uninstaller). My understanding is that each user has a unique SID e.g. HKEY_USERS\S-1-5-21-1832913631-259515069-2567909844-16342 in the Registry. The objective therefore is to return a list of users SIDs in an array and then loop through removing the String value under Run.

I can use RegGetSubkeyNames to return the list of subkeys under HKEY_USERS:

procedure RemoveAppRunRegEntries();
var
  Subkeys: TArrayOfString;
  I: Integer;
begin
  RegGetSubkeyNames(HKU, '', Subkeys);
  for I := 0 to GetArrayLength(Subkeys) - 1 do
    begin
      RegDeleteValue(HKU, Subkeys[I] + '\Software\Microsoft\Windows\CurrentVersion\Run',
        'App Run String Value');
    end;
end;

However, there are four default entries .DEFAULT, S-1-5-18, S-1-5-19 and S-1-5-20, that I believe are always the same on every Windows installation (they are all on the installs I have checked under Windows 7 and 10), plus additional identical SIDs with _Classes appended to the the end, so for the example SID above, there is also a HKEY_USERS\S-1-5-21-1832913631-259515069-2567909844-16342_Classes subkey. Therefore, before looping through, I need to find a way of removing these entries from the array, so that I only have a list of the SIDs.

Is this the best approach to be taking and how might I remove the entries from the array to leave only the unique user SIDs? Is there anything else I have not thought of?


Solution

  • You do not have to remove the keys from the array, just skip them in the loop.

    To select the correct keys, I'm checking if there are 7 dashes and no underscore in the key name:

    procedure RemoveAppRunRegEntries();
    var
      Subkeys: TArrayOfString;
      Subkey: string;
      I, J, Dashes: Integer;
    begin
      RegGetSubkeyNames(HKU, '', Subkeys);
    
      for I := 0 to GetArrayLength(Subkeys) - 1 do
      begin
        Subkey := Subkeys[I];
        Dashes := 0;
    
        for J := 1 to Length(Subkey) do
        begin
          if Subkey[J] = '-' then
          begin
            Inc(Dashes);
          end;
    
          if Subkey[J] = '_' then
          begin
            Dashes := -1;
            Break;
          end;
        end;
    
        if Dashes = 7 then
        begin
          RegDeleteValue(
            HKU, Subkey + '\Software\Microsoft\Windows\CurrentVersion\Run',
            'App Run String Value'); 
        end;
      end;
    end;