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

For some reason this snippet of code isn't removing a directory inside my registry. Directory isn't the right word, but it's the main folder all it's subkeys are in. It is full of other subkeys and subsubkeys and I want to remove the upmost "folder/key" to rid of all of it.

This code produces no error like it originally did when it told me the file could not be found. It prints "done" but when I go back into regedit, the folder/key is still sitting there smiling at me.

#!/usr/bin/perl use warnings; use strict; use Win32::TieRegistry( Delimiter=>"/", ArrayValues=>0 ); my $myway= delete $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/MyWay/"}; print "Done";
The key MyWay DOES exist, I checked it a dozen times. The original thought was we couldn't delete keys that had subkeys, but according to the example they use, it sounds like you can"
Deleting a key WARNING: The following code will delete all information about the curr +ent user's tip preferences. Actually executing this command would pro +bably cause the user to see the Welcome screen the next time they log + in and may cause more serious problems. This statement is shown as a +n example only and should not be used when experimenting. $tips= delete $Registry->{"CUser/Software/Microsoft/Windows/" . "CurrentVersion/Explorer/Tips/"};
I'm on WinXP for those who are interested. Thank you for your help!


"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

sulfericacid

Replies are listed 'Best First'.
Re: Removing keys in the registry
by davidj (Priest) on Jun 04, 2004 at 00:46 UTC
    I looked at the Win32::TieRegistry documentation on ActiveState.com. (I don't think ActivePerl's impelmentation of Win32 modules is unique.) This is a direct quite:

    "Deleting items

    You can use the Perl delete function to delete a value from a Registry key or to delete a subkey as long that subkey contains no subkeys of its own."


    hope this helps,
    davidj
Re: Removing keys in the registry (code)
by tye (Sage) on Jun 04, 2004 at 16:47 UTC

    This isn't particularly hard to solve. I typed into the Chatterbox a subroutine that does it when you asked about it there. I guess you ran off before waiting for a reply. It can be as simple as:

    sub deleteReg { my( $key, $name )= @_; for( eval { keys %{$key->{$name}} } ) { deleteReg( $key, "$name\\$_" ); } delete $key->{$name}; } deleteReg( $Registry, "HKEY_LO­CAL_MACHINE/SOFTWARE­/MyWay/", );

    Here is a more robust and efficient version (though I'm sure some will consider the above use of eval to be more robust and I agree, but I wanted to show an alternative to that):

    *isa= \&UNIVERSAL::isa; sub deleteReg { my $key= shift @_; # Registry key to delete item from my $name= shift @_; # Name of item to delete { my $item= $key->{$name}; if( ! $item ) { warn "Can't read $name in ", $key->Path(), ": $^E\n"; return; } if( ref($item) && isa($item,"HASH") ) { for my $subName ( keys %$item ) { deleteReg( $item, $subName ); } } } delete $key->{$name} or warn "Can't delete $name from ", $key->Path(), ": $^E\n"; } deleteReg( $Registry, "HKEY_LO­CAL_MACHINE/SOFTWARE­/MyWay/", );

    Another way to do it doesn't bother with values:

    sub regDelTree { my $rootKey= shift @_; # Reg key to del subtree from my $keyName= shift @_; # Name of key to delete { my $key= $rootKey->{$keyName}; if( ! $key ) { warn "Can't open $keyName in ", $rootKey->Path(), ": $^E\n"; return; } for( $key->SubKeyNames() ) { regDelTree( $key, "$_\\" ); } } delete $rootKey->{$keyName} or warn "Can't delete $keyName from ", $rootKey->Path(), ": $^E\n"; } regDelTree( $Registry, "HKEY_LO­CAL_MACHINE/SOFTWARE­/MyWay/", );

    The main reason that one of these isn't just included in the module is that dealing with errors in a general way in nested code like this is a pain to do well. The above code just punts and uses warn which is reasonable but often isn't what a user of a module would want. I've wanted to add something like this to the module and I will in a future release.

    Code untested at this point. Yes, you might have to do a little work yet. (:

    - tye        

      Hello tye,
      and thanks for this code.

      I do have a question : what does the eval do ?

      I tried to play with $key->{$name} and got a lot of hash references.
      The eval does bring the name of the key to delete. Why ?

      Also after executing this code i end up with a default value in the hive and can't find a way to delete it ?!

      Thanks if you can shed some light ,
      Z.

        what does the eval do ?

        If a registry key contains values, then keys will return the names of those values. But $key->{$aValueName} will not give you back a hash reference so the %{$key->{$name}} would fail with "Can't coerce array into hash" or something.

        sub deleteReg { my( $key, $name )= @_; for( eval { keys %{$key->{$name}} } ) { deleteReg( $key, "$name\\$_" ); } delete $key->{$name}; }

        The eval will return what keys returns if $name is a subkey name and will trap the die and return and empty list if $name is a value name. So for( eval ... ) will silently skip values.

        Also after executing this code i end up with a default value in the hive and can't find a way to delete it ?!

        You can't have a registry key without an empty default value. That is just the way the registry is.

        - tye        

Re: Removing keys in the registry
by baruch (Beadle) on Jun 04, 2004 at 04:41 UTC

    Hi, Sulfericacid... I ran this, and when MyWay had no sub-key, it was deleted as expected. When I added a sub-key, then it wouldn't delete, and as you said, there was no error message about it.

    Using regedit, I checked out the Microsoft example you gave, and found that the tips key doesn't have a sub-key. So - your problem appears to be caused by the existence of a sub-key under MyWay.


    בּרוּך

      There's "no error" reported unless you write code to report the error (or manage to produce a Perl syntax error with your code). Examples of such code (as basic as just "or die $^E") are found all over the documentation for Win32::TieRegistry.

      Not every example includes the error checking because it gets rather tiresome and often distracts from the point that the example is trying to illustrate.

      - tye