I wanted to use perl to manipulate the registry on Windows XP. According to Microsoft's website "Key names are not case sensitive. Key names cannot include a backslash (\), but any other printable or unprintable character can be used."
(http://msdn.microsoft.com/library/en-us/sysinfo/base/regcreatekey.asp).
Depending on the locale in effect at the time you create the key, it seems virtually any keyname is possible. This also supports the creation of multi-byte characterset keys and keynames or valuenames with unprintable characters.
I wrote a simple routine to "iterate" all the keynames and their values. This worked fine for the HKEY_CLASSES sub-key. However for HKEY_CURRENT_USER (me), Microsoft's Sound-font selector for system actions had created some odd keynames.
Now one might say "oh, just delete those keys, they are of no use, anyway", but, I answer -- they are of excellent use: they point out a bug in the interface.
To date, no one know's exactly where the bug is -- if it is in the Win32 routines or if it is in Perl. I'm thinking there is a 30% chance it's in Perl and not specific but I don't know enough perl to verify this.
I do know that others rewrote my iteration routine and one person tried the older ("deprecated") Win32::Registry functions and none were able to iterate the suspect keys.
I wrote a simple test-case registry file that one can use to create the problem keynames. NOTE: this example file won't harm one's registry and can easily be deleted in the Registry Editory.
Just to "get it right" in case it doesn't display/store or copy correctly above, here is the same file encoded using uuencode:--- Reg5 file to create sample keys: --- Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\_ATEST_\.Default\Curren0] @="myvalue1" [HKEY_CURRENT_USER\_ATEST_\.Default\current0?] @="myvalue2" [HKEY_CURRENT_USER\_ATEST_\.Default\current0肼] @="myvalue3" [HKEY_CURRENT_USER\_ATEST_\AppGPFault\Curren0] @="myvalue4" [HKEY_CURRENT_USER\_ATEST_\AppGPFault\current0肼] @="myvalue5" -------------
------- here is the perl program to list the above key:begin 640 reg5-format.reg M__Y7`&D`;@!D`&\`=P!S`"``4@!E`&<`:0!S`'0`<@!Y`"``10!D`&D`=`!O M`'(`(`!6`&4`<@!S`&D`;P!N`"``-0`N`#``,``-``H`#0`*`%L`2`!+`$4` M60!?`$,`50!2`%(`10!.`%0`7P!5`%,`10!2`%P`7P!!`%0`10!3`%0`7P!< M`"X`1`!E`&8`80!U`&P`=`!<`$,`=0!R`'(`90!N`#``!@!=``T`"@!``#T` M(@!M`'D`=@!A`&P`=0!E`#$`(@`-``H`#0`*`%L`2`!+`$4`60!?`$,`50!2 M`%(`10!.`%0`7P!5`%,`10!2`%P`7P!!`%0`10!3`%0`7P!<`"X`1`!E`&8` M80!U`&P`=`!<`&,`=0!R`'(`90!N`'0`,``_`%T`#0`*`$``/0`B`&T`>0!V M`&$`;`!U`&4`,@`B``T`"@`-``H`6P!(`$L`10!9`%\`0P!5`%(`4@!%`$X` M5`!?`%4`4P!%`%(`7`!?`$$`5`!%`%,`5`!?`%P`+@!$`&4`9@!A`'4`;`!T M`%P`8P!U`'(`<@!E`&X`=``P`+R`70`-``H`0``]`"(`;0!Y`'8`80!L`'4` M90`S`"(`#0`*``T`"@!;`$@`2P!%`%D`7P!#`%4`4@!2`$4`3@!4`%\`50!3 M`$4`4@!<`%\`00!4`$4`4P!4`%\`7`!!`'``<`!'`%``1@!A`'4`;`!T`%P` M0P!U`'(`<@!E`&X`,``&`%T`#0`*`$``/0`B`&T`>0!V`&$`;`!U`&4`-``B M``T`"@`-``H`6P!(`$L`10!9`%\`0P!5`%(`4@!%`$X`5`!?`%4`4P!%`%(` M7`!?`$$`5`!%`%,`5`!?`%P`00!P`'``1P!0`$8`80!U`&P`=`!<`&,`=0!R M`'(`90!N`'0`,`"\@%T`#0`*`$``/0`B`&T`>0!V`&$`;`!U`&4`-0`B``T` &"@`-``H` ` end
#!/perl/bin/perl -w use UTF8; use Win32::TieRegistry 0.24 ; #"Classes" for HKEY_CLASSES_ROOT #"CUser" for HKEY_CURRENT_USER #"LMachine" for HKEY_LOCAL_MACHINE #"Users" for HKEY_USERS #"CConfig" for HKEY_CURRENT_CONFIG select STDERR;$|=1; select STDOUT;$|=1; my $col=1; $keyname='CUser\\_ATEST_'; print_key($Registry->{$keyname},$keyname,0); sub print_key { my ($cur_key, $keyname, $level)=@_; if ($col) { print "\n"; $col=0; } print " " x $level; $col=2; print "$keyname\\";my $nospaces=1; foreach $member ($cur_key->MemberNames) { if ($member =~ m|^(.+)\\$|) { $keyname=$1; if ($col) { print "\n"; $col=0; } $nospaces=0; print_key($cur_key->{"$keyname\\"}, "$keyname",$level+1); } elsif ($member =~ m|^\\(.*)$|) { $valuename=$1; $value=$cur_key->GetValue("$valuename"); $value=(defined $value)?$value:"(value not set)"; $value=(length($value))?$value:"(null)"; if (!$nospaces) {print " " x ($level+1); $col+=2;}; $nospaces=0; print "$valuename => $value"; if ($col) { print "\n"; $col=0; } } } }
CUser\_ATEST_\ .Default\ Curren0♠\ => myvalue1 current0?\ => myvalue2 current0?\ => myvalue2 AppGPFault\ Curren0♠\ => myvalue4 current0?\Can't call method "MemberNames" on an undefined value at + ./test.pl line 34.
As it doesn't seem specific to TieRegistry and is in the Registry function of Win32 as well, the problem would seem to lie either in "Win32" or in perl. As I mentioned before, I'd give it about 2:1 odds of being in perl but I've no idea how Win32 works.
As it stands now, I have this "vague" uneasy feeling about how robust perl is in handling unexpected sequences in string data.
Many thanks for anyone who can isolate this problem....
Linda
In reply to possible perl bug or, at least, Win32::[TieRegistry|Registry] bug with difficult keynames by perl-diddler
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |