Ian Branch 127 Posted September 8, 2019 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
Ian Branch 127 Posted September 8, 2019 (edited) 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. 😞 Ian Edited September 8, 2019 by Ian Branch Share this post Link to post
David Heffernan 2345 Posted September 8, 2019 Don't you need to empty the key before you delete it? Share this post Link to post
David Heffernan 2345 Posted September 8, 2019 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
Ian Branch 127 Posted September 8, 2019 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
Uwe Raabe 2057 Posted September 8, 2019 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
FredS 138 Posted September 8, 2019 Maybe you need to use a WOW key: Accessing an Alternate Registry View Share this post Link to post
David Heffernan 2345 Posted September 8, 2019 11 minutes ago, FredS said: Maybe you need to use a WOW key: Accessing an Alternate Registry View No. It's in HKCU. Share this post Link to post
Remy Lebeau 1397 Posted September 10, 2019 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
Ian Branch 127 Posted September 10, 2019 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
Ian Branch 127 Posted September 10, 2019 Yep. Screwed it up. How do you get the individual quote sections into the reply please? 1 Share this post Link to post
Uwe Raabe 2057 Posted September 11, 2019 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: Share this post Link to post
Ian Branch 127 Posted September 11, 2019 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
Ian Branch 127 Posted March 19, 2021 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
Uwe Raabe 2057 Posted March 19, 2021 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. 1 Share this post Link to post
Ian Branch 127 Posted March 19, 2021 Ahh. Excellent! Thanks Uwe. Works fine now. Regards, Ian Share this post Link to post
Remy Lebeau 1397 Posted March 20, 2021 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
Ian Branch 127 Posted March 20, 2021 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
Ian Branch 127 Posted March 20, 2021 Hmmmm. Looking into winapi.windows, there is no RegDeleteTree. :-( Share this post Link to post
Guest Posted March 20, 2021 (edited) 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? 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 March 20, 2021 by Guest Share this post Link to post
Nigel Thomas 35 Posted March 20, 2021 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
FredS 138 Posted March 20, 2021 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
KodeZwerg 54 Posted March 20, 2021 (edited) { 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 March 20, 2021 by KodeZwerg worked on example Share this post Link to post
Guest Posted March 20, 2021 (edited) 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 March 20, 2021 by Guest Share this post Link to post