Search code examples
perlregistryregedit

Delete a Entire Reg Directory using Perl


I would like to Delete the Registry in Windows Machine using a perl command. How can I do that . I tried few command from Internet it is getting executed but not deleted Please provide help !! The below code executes , but doesn't delete the Reg Key

use warnings;
use strict;

use Win32::TieRegistry( Delimiter=>"/", ArrayValues=>0 );

my $myway= delete $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/Keypath"};

print "Done";

Solution

  • First you need the right permission to delete a registry key (try run the Perl script from a CMD with admin privileges), second according to the documentation you can only delete a key provided it does not contain any subkeys:

    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.

    Third, even if you run with admin privileges there can still be keys that you cannot delete, see this Q&A for more information.

    So if you want to delete an entire subtree, you need to iterate bottom up through the tree and delete each subkey separately. Here is an example:

    use feature qw(say);
    use warnings;
    use strict;
    use Data::Dumper qw(Dumper);
    use Win32::RunAsAdmin qw(force);
    use Win32API::Registry qw(regLastError KEY_READ KEY_WRITE);
    use Win32::TieRegistry( Delimiter=>"/", ArrayValues=>0 );
    {
        # Choose the top root node that should be deleted
        # Note: This and all its subkeys will be deleted from the registry.
        # Note: Will only succeed if you have permission to write to each sub key
        my $top_key_name = "HKEY_CLASSES_ROOT/Directory/Background/shell/Foo";
        my $tree = $Registry->Open(
            $top_key_name,  
           { Access=>KEY_READ()|KEY_WRITE(), Delimiter=>"/" } 
        );
        die "Could not open key $top_key_name: $^E" if !defined $tree;
        delete_subtree( $tree, my $level = 0);
    }
    
    sub delete_subtree {
        my ($tree, $level) = @_;
        my $path = $tree->Path();
        my @subkeys = $tree->SubKeyNames();
        for my $name (@subkeys) {
            my $subtree = $tree->{$name."/"};
            if (!defined $subtree) {
                die "Cannot access subkey $name for $path: " . regLastError() . ". Abort.";
            }
            if (ref $subtree) {
                delete_subtree($subtree, $level + 1);
            }
            else {
                die "Subkey $name for $path is not a hash ref. Abort.";
            }
        }
        
        # assuming the previous recursive code has deleted all sub keys of the 
        # current key, we can now try delete this key
        say "Trying to delete $path ..";
        my $res = delete $Registry->{$path};
        if (!defined $res) {
            die "..Failed to delete key : $^E";
        }
        else {
            say "  -> success";
        }
    }