Jump to content
Ian Branch

Delete a Registry Key...

Recommended Posts

Hi Team,

Not sure what is going on here..  Just about to tear what little hair I have out.

I am trying to delete a registry key.  Win 10, 64bit, D10.3.2.  32bit App.

I have the following code..

procedure TMainForm.ClearKey1Click(Sender: TObject);
var
  reg: TRegistry;
begin
  //
    MessageBeep(MB_ICONINFORMATION);
    reg := TRegistry.Create(KEY_WRITE);
    reg.RootKey := HKEY_CURRENT_USER;

    reg.DeleteKey('DBiW\DBiW\JTGrid');

    reg.CloseKey();
  //
end;

It runs without issue/error but does not delete the Key. :-(

Is this some 64bit gotcha?

I need it to work in 64 & 32 bit environments.

Yes, System.Win.Registry is in the Uses list.

Thoughts/suggestions appreciated.

Share this post


Link to post

Hi David,

No.  It is holding a set of string properties from a Grid.  See picture.

As you can see I simplified the above code.

Somehow I got two pictures in here. 😞

 

IanScreenshot_4.png.3167feee4ab0a0ea6d48ea44e1f5b974.png

Screenshot_4.png

Edited by Ian Branch

Share this post


Link to post

OK, just looked tlat the documentation and it explains it all. You have to delete the sub keys. And you won't get an error in your code because the function returns a boolean indicating success or failure. You didn't check this. 

 

Let me gently suggest that rather than tearing hair out, the documentation may help!

Share this post


Link to post

Hi David,

Feel free to point out the error of my ways.  I used to be perfect, now I'm not so sure. ;-)

I have been lead astray by the ClearKey function above being called immediately after the JobTicket Form Modal Show from within the Menu call.

I separated it out and called the routine separately and it works.  With all the key data there.

Yes, I know, back to front but I had every expectation it would work. :-(

Thanks for your input and gentle prompt. :-)

Regards,

Ian

 

Share this post


Link to post
1 hour ago, David Heffernan said:

just looked tlat the documentation and it explains it all. You have to delete the sub keys.

Seems like the docs are mistaken here. The source code is more reliable and shows that subkeys are internally deleted.

Share this post


Link to post

 

On 9/7/2019 at 11:16 PM, Ian Branch said:

I have the following code..


    reg.RootKey := HKEY_CURRENT_USER;
    reg.DeleteKey('DBiW\DBiW\JTGrid');

 

Is "HKCU\DbiW\DBiW\TJGrid" the actual path to your subkey?  Your screenshot does not show the whole tree.  It is very unusual to see a user-defined key that is not located under one of the system-provided keys, such as "HKCU\Software" (where they usually belong).

On 9/7/2019 at 11:16 PM, Ian Branch said:

It runs without issue/error but does not delete the Key. 😞

TRegistry.DeleteKey() returns a boolean to indicate success, which you are not checking.  If it returns False, check the TRegistry.LastError and/or TRegistry.LastErrorMsg properties, they tell you why if failed.

On 9/8/2019 at 12:29 AM, David Heffernan said:

Don't you need to empty the key before you delete it? 

Despite what the documentation claims, TRegistry.DeleteKey() actually handles this internally for you.  It runs a recursive loop to delete all subkeys before then deleting the requested key.  You don't have to delete them manually (though you probably should so you can perform error handling on each one).  Otherwise, use the Win32 RegDeleteTree() or SHDeleteKey() function instead and let the OS delete all of the subkeys for you.

Share this post


Link to post
2 hours ago, Remy Lebeau said:

 

OK first try at quoting and I may screw it up.

I abbreviated the path for the snippet.

"HKCU\Software" - You are correct and I will ammend it.

2 hours ago, Remy Lebeau said:

Function return, - Probably should have.

2 hours ago, Remy Lebeau said:

Despite what the documentation claims, TRegistry.DeleteKey() actually handles this internally for you.  It runs a recursive loop to delete all subkeys before then deleting the requested key.  You don't have to delete them manually (though you probably should so you can perform error handling on each one).  Otherwise, use the Win32 RegDeleteTree() or SHDeleteKey() function instead and let the OS delete all of the subkeys for you.

This is what I found.

Share this post


Link to post
8 hours ago, Ian Branch said:

How do you get the individual quote sections into the reply please?

Highlight the text with the mouse and click on the then appearing Quote bubble: 

11-09-_2019_09-15-48.gif

Share this post


Link to post
1 minute ago, Uwe Raabe said:

Highlight the text with the mouse and click on the then appearing Quote bubble: 

Thanks Uwe, appreciated.

 

Ian

Share this post


Link to post

Hi Team,

D10.4.2, 32 bit App.

I am trying to implement this on a Win 10 PC.

 

 

procedure TMainForm.Button1Click(Sender: TObject);
var
  reg: TRegistry;
begin
  //
  MessageBeep(MB_ICONINFORMATION);
  //
  reg := TRegistry.Create(KEY_WRITE);
  reg.RootKey := HKEY_CURRENT_USER;
  //
  if reg.DeleteKey('Software\MyKey') then
    showmessage('MyKey registry key deleted.')
  else
  begin
    showmessage('MyKey registry key was NOT deleted.'+#13#10+'Error message is - '+reg.LastErrorMsg);
  end;
  //
  reg.CloseKey();
  //
end;

The key is most assuredly there.

I get an access denied error.  Maybe not surprising with Win 10 these day.

I tried running the App with Admin privileges but same issue.

Has anybody got a work around/solution for this please?

 

Regards & TIA,

Ian

Share this post


Link to post

Any subkeys of the key need to be deleted first. TRegistry.DeleteKey already takes care of that, but it needs KEY_ENUMERATE_SUB_KEYS access for that, which is not included in KEY_WRITE. Try KEY_ALL_ACCESS.

  • Like 1

Share this post


Link to post
1 hour ago, Uwe Raabe said:

Any subkeys of the key need to be deleted first. TRegistry.DeleteKey already takes care of that, but it needs KEY_ENUMERATE_SUB_KEYS access for that, which is not included in KEY_WRITE. Try KEY_ALL_ACCESS.

KEY_ALL_ACCESS is meant for admins only.  You should specify only the exact rights you actually need (which FYI, TRegistry.DeleteKey() also requires KEY_QUERY_VALUE, since it calls RegQueryInfoKey() to determine the number of subkeys and the maximum subkey name length), eg:

reg := TRegistry.Create(_DELETE or KEY_ENUMERATE_SUB_KEYS or KEY_QUERY_VALUE);

Otherwise, just use the Win32 RegDeleteTree() or SHDeleteKey() function instead of TRegistry.DeleteKey(), and let the OS handle the necessary recursion.

Share this post


Link to post

Hi Remy,

Happy to try RegDeleteTree() but I can't get Delphi to recognise it.

Obviously I need something in the Uses but I can't find what.  I have Winapi.windows in the uses att.

 

Ian.

Share this post


Link to post
Guest

hi @Ian Branch 

 

here my test using TRegisty with 2 sublevels and in last, I have a "key=valuexxx";

  • dont include "\SOFTWARE\" in your Delete key... because you dont delete it, you see?

 

image.thumb.png.6f6043ec05a3699cf23705903aee95b2.png

uses
  Registry;

procedure TForm1.Button1Click(Sender: TObject);
var
  lRegistry: TRegistry;
begin
  lRegistry := TRegistry.Create;
  try
    // Computador\HKEY_CURRENT_USER\SOFTWARE\KeyTestToDeleteTreeLevel0
    try
      //
      lRegistry.RootKey := HKEY_CURRENT_USER; // Start from here... or be, first, define the root to work... YOU can define HKEY...+ SOFTWARE togheter, you see?
      //
      if lRegistry.OpenKey('SOFTWARE', false) then // open the level "before"
      begin
        if lRegistry.DeleteKey('KeyTestToDeleteTreeLevel0') then  // delete from here and so...
          ShowMessage('all subkeys was deleted below and include this level')
        else
          ShowMessage('It was not possible delete this level... maybe it dont exist or have some privilegies defined... or any other thing ... :>) ');
      end;
    except
      on E: Exception do
        ShowMessage('my error: ' + sLineBreak + E.Message);
    end;
  finally
    lRegistry.CloseKey;
  end;
end;

 

if it's not possible delete "tree", you cannot have "privilegies in your key to open it or delete it... the rest, it's works!!!

 

hug

Edited by Guest

Share this post


Link to post
1 hour ago, Ian Branch said:

Hi Remy,

Happy to try RegDeleteTree() but I can't get Delphi to recognise it.

Obviously I need something in the Uses but I can't find what.  I have Winapi.windows in the uses att.

 

Ian.

I presume you need to load it dynamically from advapi32.dll, not tried it myself.

Share this post


Link to post

Declaration:

{$IF NOT DECLARED(RegDeleteTree)}
function RegDeleteTree(hKey: HKEY; lpSubKey: LPCTSTR):LONG ; stdcall; external advapi32 name 'RegDeleteTreeW' delayed;
{$IFEND DECLARED(RegDeleteTree)}

 

Share this post


Link to post
{ TRegistry wrapper }
function RegDelKey(const RootKey: HKEY; const Key: string): Boolean;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_WRITE);
  try
    Reg.RootKey := RootKey;
    Reg.LazyWrite := False;
    Result := ((Reg.KeyExists(Key)) and (Reg.DeleteKey(Key)));
    Reg.CloseKey;
  finally
    Reg.Free;
  end;
end;

// example
// if RegDelKey(HKEY_CURRENT_USER, 'SOFTWARE\MyKey\') then

how about such? @Ian Branch

Edited by KodeZwerg
worked on example

Share this post


Link to post
Guest
46 minutes ago, KodeZwerg said:

how about such?

by default:
 

Quote

Creates a TRegistry object for an application.

Create instantiates a TRegistry object and sets the RootKey property to HKEY_CURRENT_USER and the LazyWrite property to true. If an AAccess parameter is supplied, this value is used to initialize the Access property. Otherwise, Access is initialized to KEY_ALL_ACCESS.

hug

Edited by Guest

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×