Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Unable to delete registry keys using Win32::TieRegistry

by liverpole (Monsignor)
on Sep 01, 2010 at 00:03 UTC ( [id://858245]=perlquestion: print w/replies, xml ) Need Help??

liverpole has asked for the wisdom of the Perl Monks concerning the following question:

Greetings fellow monks,

I'm not sure if my problem is with my misunderstanding of how the registry works, or my somehow failing to use the Win32::TieRegistry module correctly.  My intent is to delete the key 'HKEY_CLASSES_ROOT/Folder/shell/xyzzy_1' from the Windows XP registry on my laptop computer.

First of all, here's my code:

#!/usr/bin/perl -w # # Attempt to delete 'HKEY_CLASSES_ROOT/Folder/shell/xyzzy_1' from the # Windows Registry, using Win32::TieRegistry. ## ############# # Libraries # ############# use strict; use warnings; use Data::Dumper; use Win32::TieRegistry( Delimiter => '/' ); ################ # Main Program # ################ # Step 1 -- assign variables my $label = "xyzzy_1"; my $key = 'HKEY_CLASSES_ROOT/Folder/shell'; my $h_shell = $Registry->{$key}; (defined $h_shell) or die "Unable to find registry key '$key'\n"; # Step 2 -- Display all keys for HKEY_CLASSES_ROOT/Folder/shell print "[Values for '$key']\n"; my $idx = 0; foreach my $key (keys %$h_shell) { printf " %3d. %s\n", ++$idx, $key; } print "\n\n"; # Step 3 -- Validate that the label 'xyzzy_1' was found if (!exists($h_shell->{$label})) { die "No such label for '$key' => '$label'\n"; } # Step 4 -- Delete 'xyzzy_1' from 'HKEY_CLASSES_ROOT/Folder/shell' print "Deleting label '$label' ...\n"; my $result = delete($h_shell->{$label}); print "Result of delete: '$result'\n";

Prior to running the program, I created a registry key "HKEY_CLASSES_ROOT/Folder/shell/xyzzy_1", which along with the existing keys for the parent key look like this according to regedit (note my use of '###' for the folder icon):

[+]-### FName.Factoid [+]-### FName.Factoid.2 [+]-### fndfile {+]-### Folder | |--### DefaultIcon | [-]-### shell | | [+]--### explore | | [+]--### open | | |---### xyzzy_1 | [+]-### shellex [+]-### fonfile [+]-### FormHost.FormHost

When I run the program, the output I get is:

D:\Tools\rmfolder>regtest.pl [Values for 'HKEY_CLASSES_ROOT/Folder/shell'] 1. explore/ 2. open/ 3. xyzzy_1/ Deleting label 'xyzzy_1' ... Result of delete: 'The system cannot find the file specified. '

Can anyone suggest why the delete isn't apparently working (both from the error message, and the fact that it still shows up in the registry)?  Am I missing some other step or steps?  I'm using Win32::TieRegistry version 0.20 (which comes with my ActiveState Perl version 5.10.0); should I be updating to a later version of Win32::TieRegistry?

Thanks in advance for any help!


s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

Replies are listed 'Best First'.
Re: Unable to delete registry keys using Win32::TieRegistry
by liverpole (Monsignor) on Sep 01, 2010 at 00:51 UTC
    Well, I may have solved my own problem.

    After reading through the documentation some more, I found the Open method:

    $subKey= $key->Open( $sSubKey, $rhOptions ) The Open method opens a Registry key and returns a new Win32::TieR +egistry object associated with that Registry key. If Open is called via a refe +rence to a tied hash, then Open returns another reference to a tied hash. Other +wise Open returns a simple object and you should then use TiedRef to get a refer +ence to a tied hash. $sSubKey is a string specifying a subkey to be opened. Alternately + $sSubKey can be a reference to an array value containing the list of increasing +ly deep subkeys specifying the path to the subkey to be opened. ...

    Which seems to do the trick in my modified program:

    #!/usr/bin/perl -w # # Attempt to delete 'HKEY_CLASSES_ROOT/Folder/shell/xyzzy_1' from the # Windows Registry, using Win32::TieRegistry. # # This version uses the 'Open' method -- Success! ## ############# # Libraries # ############# use strict; use warnings; use Data::Dumper; use Win32::TieRegistry( Delimiter => '/' ); ################ # Main Program # ################ # Step 1 -- assign to the 'Folder' key my $label = "xyzzy_1"; my $key = 'HKEY_CLASSES_ROOT/Folder'; my $h_folder = $Registry->{$key}; (defined $h_folder) or die "Unable to find registry key '$key'\n"; # Step 2 -- open at the 'shell' subkey my $h_shell = $h_folder->Open('shell', { 'Delimiter' => '/' }); $h_shell or die "Unable to open subkey 'shell' (of key '$key')\n"; # Step 3 -- Display values for the 'shell' subkey print "[Values for '$key/shell']\n"; my $idx = 0; foreach my $key (keys %$h_shell) { printf " %3d. %s\n", ++$idx, $key; } print "\n\n"; # Step 4 -- Validate that the label 'xyzzy_1' was found if (!exists($h_shell->{"$label/"})) { die "No such label for '$key' => '$label'\n"; } # Step 5 -- Delete 'xyzzy_1' from the 'shell' subkey print "Deleting label '$label' ...\n"; my $result = delete($h_shell->{"$label/"}); printf "Result of delete: '%s'\n", Dumper($result);

    One caveat is that, if the regedit program is open, you must refresh its state after the delete (View > Refresh or function key F5), otherwise the display will continue to show the deleted key (eg. 'xyzzy_1'), but clicking on it (and other operations) will give a regedit error.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

      Just don't leave off the trailing '/'. All of the other changes you made probably have no bearing on the problem. In particular, your use of Open() probably makes no difference.

      If you leave off the trailing '/', then the module must try to guess whether you mean to delete a value or to delete a subkey. The logic to detect which seems the likely intent is more fragile and likely fails in this particular case.

      - tye        

        Thanks for your answer.  I was kind of hoping you might comment here, since it appears you wrote the original module, and it's nice to get advice directly from the expert.

        I don't think I was missing a trailing '/' in my original code, but now I'm not sure; it's certainly possible.  I'll have to go back and check tomorrow.  

        Since I have your ear, (more accurately "eyes"), is there any easy way to delete a whole subkey, which may or may not have subkeys or subvalues?  From what I've read of the documentation there's no way to do so, (and I've already written code that seems to work for this), but it seems like a potentially useful option.

        It's a very useful module!  I've got some ideas for things I'd like to add to the Windows context menu, and this seems just the I need to automate it. :-)


        s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://858245]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (6)
As of 2024-03-28 11:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found