For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > February 2005 > Perl Hash problem (with registry)









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Perl Hash problem (with registry)
thomasjbs@yahoo.com

2005-02-23, 8:57 am

Getting strange error message: "Can't coerce array into hash at test.pl
line 21 with the following code: (line 22 with added comment)

I'm very new at using hashes and Perl on registry. The strange part is
that it gets through processing about 50 items before the error occurs.

The goal is to simply read the registy and print out a list of
installed applications. Although there might be simple methods to do
this, the secondary goal is to learn to use hashes.

Apparently the data is stored as a hash inside a hash.

Anyone know what's going on?

(run on Windows XP system with Activestate perl).

use Win32::Registry;
my $Register =
" Software\\Microsoft\\Windows\\CurrentVer
sion\\Uninstall";
my ($hkey, @key_list, $key, @klist);
$cnt = 0;

$HKEY_LOCAL_MACHINE->Open($Register,$hkey)|| die $!;
$hkey->GetKeys(\@key_list);
print "$Register keys\n";
foreach $key (@key_list)
{
$tmpkey = $Register . "\\" . $key . $DisplayName;
$HKEY_LOCAL_MACHINE->Open($tmpkey,$q) or next;
$q->GetValues(\%klist);

#print $klist{'Display Name'},"\n";
while (($k,$d)=each(%klist)) {
if (lc $k eq "display name") {
print $tmpkey,"\n";
print $d,"\n";;
### Error is next line ###
$d = %$d;
print $k," ",$d,"\n";
#@e = %$d;
}
}
$q->Close();
# $cnt++;

print "$key\n";
}
print $cnt;
$hkey->Close();

Dave Weaver

2005-02-23, 8:57 am

On 23 Feb 2005 00:02:27 -0800, thomasjbs@yahoo.com <thomasjbs@yahoo.com> wrote:
> Getting strange error message: "Can't coerce array into hash at test.pl
> line 21 with the following code: (line 22 with added comment)


> $q->GetValues(\%klist);

....
> while (($k,$d)=each(%klist)) {

....
> $d = %$d;


What do you expect that last line to do?


I know nothing about Win32::Registry, but according to the docs:

GetValues:
Populates the supplied hash reference with entries of the form

$value_name => [ $value_name, $type, $data ]

i.e. the value of each entry ($d in your code) is an array ref. You
are dereferencing it as though it was a hash ref.

Instead of:
> $d = %$d;
> print $k," ",$d,"\n";


try:
print "key: $k - $name: $d->[0] type: $d->[1] data: $d->[2]";

(untested).
Peter Wyzl

2005-02-23, 8:58 am

<thomasjbs@yahoo.com> wrote in message
news:1109145747.375288.82950@g14g2000cwa.googlegroups.com...
: Getting strange error message: "Can't coerce array into hash at test.pl
: line 21 with the following code: (line 22 with added comment)
:
: I'm very new at using hashes and Perl on registry. The strange part is
: that it gets through processing about 50 items before the error occurs.
:
: The goal is to simply read the registy and print out a list of
: installed applications. Although there might be simple methods to do
: this, the secondary goal is to learn to use hashes.
:
: Apparently the data is stored as a hash inside a hash.
:
: Anyone know what's going on?

Maybe you have a problem in the registry? It seems to work on my system,
with several caveats:
:
: (run on Windows XP system with Activestate perl).

use warnings;
use strict;

# Will report a few little problems as detailed below.

: use Win32::Registry;

The docs say this is an obsolete module, use Win32::TieRegistry instead...


: my $Register =
: " Software\\Microsoft\\Windows\\CurrentVer
sion\\Uninstall";
: my ($hkey, @key_list, $key, @klist);

@klist is declared here, but below you use %klist...

: $cnt = 0;

Here you set $cnt, and then never increment it...

: $HKEY_LOCAL_MACHINE->Open($Register,$hkey)|| die $!;
: $hkey->GetKeys(\@key_list);

: print "$Register keys\n";
: foreach $key (@key_list)
: {
: $tmpkey = $Register . "\\" . $key . $DisplayName;

$DisplayName is used without being declared and is a null value

: $HKEY_LOCAL_MACHINE->Open($tmpkey,$q) or next;

What do you expect $q to be at this point?

: $q->GetValues(\%klist);
:
: #print $klist{'Display Name'},"\n";
: while (($k,$d)=each(%klist)) {
: if (lc $k eq "display name") {
: print $tmpkey,"\n";
: print $d,"\n";;
: ### Error is next line ###
: $d = %$d;
: print $k," ",$d,"\n";
: #@e = %$d;
: }
: }
: $q->Close();
: # $cnt++;
:
: print "$key\n";
: }
: print $cnt;
: $hkey->Close();

My head hurts....

P
--
print "Just another Perl Hacker";


thomasjbs@gmail.com

2005-02-23, 3:59 pm


Dave Weaver wrote:
> On 23 Feb 2005 00:02:27 -0800, thomasjbs@yahoo.com

<thomasjbs@yahoo.com> wrote:
test.pl[color=darkred]
>
> ...
> ...
>
> What do you expect that last line to do?
>


Without the last line, the output shows array hashes instead of the
actual data. Perhaps some of the entries do not need to be extracted
from the hash, but I don't how to tell whether a value needs to be
extracted from the hash.

> I know nothing about Win32::Registry, but according to the docs:
>
> GetValues:
> Populates the supplied hash reference with entries of the form
>
> $value_name => [ $value_name, $type, $data ]
>
> i.e. the value of each entry ($d in your code) is an array ref. You
> are dereferencing it as though it was a hash ref.
>
> Instead of:
>
> try:
> print "key: $k - $name: $d->[0] type: $d->[1] data: $d->[2]";
>
> (untested).


Thanks, I'll try that.

thomasjbs@gmail.com

2005-02-23, 3:59 pm


Peter Wyzl wrote:
> <thomasjbs@yahoo.com> wrote in message
> news:1109145747.375288.82950@g14g2000cwa.googlegroups.com...
> : Getting strange error message: "Can't coerce array into hash at

test.pl
> : line 21 with the following code: (line 22 with added comment)
> :
> : I'm very new at using hashes and Perl on registry. The strange

part is
> : that it gets through processing about 50 items before the error

occurs.
> :
> : The goal is to simply read the registy and print out a list of
> : installed applications. Although there might be simple methods to

do
> : this, the secondary goal is to learn to use hashes.
> :
> : Apparently the data is stored as a hash inside a hash.
> :
> : Anyone know what's going on?
>
> Maybe you have a problem in the registry? It seems to work on my

system,
> with several caveats:
> :
> : (run on Windows XP system with Activestate perl).
>
> use warnings;
> use strict;
>
> # Will report a few little problems as detailed below.
>
> : use Win32::Registry;
>
> The docs say this is an obsolete module, use Win32::TieRegistry

instead...

I tried TieRegistry first, but I could not find any working examples
(even the examples in the documentation failed.)

>
> : my $Register =
> : " Software\\Microsoft\\Windows\\CurrentVer
sion\\Uninstall";
> : my ($hkey, @key_list, $key, @klist);
>
> @klist is declared here, but below you use %klist...
>
> : $cnt = 0;
>
> Here you set $cnt, and then never increment it...
>


I tried *many* different methods to extract the data from the hash - I
was aware that $cnt is notused in the most recent attempt.

> : $HKEY_LOCAL_MACHINE->Open($Register,$hkey)|| die $!;
> : $hkey->GetKeys(\@key_list);
>
> : print "$Register keys\n";
> : foreach $key (@key_list)
> : {
> : $tmpkey = $Register . "\\" . $key . $DisplayName;
>
> $DisplayName is used without being declared and is a null value
>

Originally that was "DisplayName". the '$' was a typo in one of the
edits.

> : $HKEY_LOCAL_MACHINE->Open($tmpkey,$q) or next;
>
> What do you expect $q to be at this point?
>
> : $q->GetValues(\%klist);


I thought $q was a handle for the Registry read. $q seemed to be
working fine as I got a lot of data into the klist hash.

> :
> : #print $klist{'Display Name'},"\n";
> : while (($k,$d)=each(%klist)) {
> : if (lc $k eq "display name") {
> : print $tmpkey,"\n";
> : print $d,"\n";;
> : ### Error is next line ###
> : $d = %$d;
> : print $k," ",$d,"\n";
> : #@e = %$d;
> : }
> : }
> : $q->Close();
> : # $cnt++;
> :
> : print "$key\n";
> : }
> : print $cnt;
> : $hkey->Close();
>
> My head hurts....


Mine too.

>
> P
> --
> print "Just another Perl Hacker";


Thomas Kratz

2005-02-28, 3:58 pm

thomasjbs@gmail.com wrote:
> Peter Wyzl wrote:
>
> instead...
>
> I tried TieRegistry first, but I could not find any working examples
> (even the examples in the documentation failed.)


They should not. But I agree: it takes some time to get used to it.

Here is a much shorter example to achieve this task with Win32::TieRegistry:

use strict;
use warnings;

use Win32::TieRegistry(Delimiter => '/');

my $key = 'LMachine/Software/Microsoft/Windows/CurrentVersion/Uninstall';

foreach my $subkey ( keys(%{$Registry->{$key}}) ) {
# beware: $subkey comes with a trailing slash
my $name = $Registry->{"$key/$subkey/DisplayName"} || 'no name found';
print "$name\n";
}

Thomas

--
$/=$,,$_=<DATA>,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k^.-
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com