We help IT Professionals succeed at work.

reading windows regsitry with perl

ranadhir
ranadhir asked
on
Medium Priority
481 Views
Last Modified: 2012-05-07
We have a simple program to read the windows registry:

eval 'use Win32::TieRegistry( Delimiter=>"/");';
 if ($@)
 {
        DEBUG("Could not perform the transaction. Reason is:\n$@\n");
}
$key = $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/ODBC/ODBC.INI/"} or $error="ERROR , $^E\n";
DEBUG(" open ini entries from registry : $error \n");

This fails for any key in the registry with teh exception :
DEBUG:   open ini entries from registry : ERROR , The system cannot find the file specified

Who do i keep getting this?
Any help will be much appreaciated
Comment
Watch Question

Suhas .Senior QA Manager
CERTIFIED EXPERT

Commented:
Hi ranadhir,
the attached code worked fine for me...
please check at your end.

Cheers...
Suhas

use Win32::TieRegistry;
$Registry->Delimiter("/");
 
$odbc_content = $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/ODBC/ODBC.INI/"} or $error="ERROR , $^E\n";
foreach my $odbc_data (keys(%{$odbc_content}))
    {
 
        $odbc_data=~s/^\/+//sg;
        print "$odbc_data\n";
    }

Open in new window

Author

Commented:
dont you need to declare the 'Registry' variable?
Suhas .Senior QA Manager
CERTIFIED EXPERT

Commented:
No that is called from the Win32::TierRegistry module...

For more details please refer http://search.cpan.org/~adamk/Win32-TieRegistry-0.26/lib/Win32/TieRegistry.pm

Cheers...
Suhas

Author

Commented:
Not using eval seems to open up the registry.
However for a sub-node if we again go to access  I get problem again.
How do i access the sub-node?

$key = $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/ODBC/ODBC.INI/"} or $error="ERROR , $^E\n";
EMD_PERL_DEBUG(" open ini entries from registry : $error \n");
my @members=keys( %{$key} );
foreach (@members){
if (m/^(.*)\/$/) {
$odbcnode=$key->{$1};//This again gives the same problem
}
Top Expert 2009

Commented:

#!/perl/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Win32::TieRegistry;
$Registry->Delimiter('/');
 
my $key = $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/ODBC/ODBC.INI/"}
  or die "Could not get registry entry1: $^E\n";
 
my @members=keys %$key;
foreach (@members){
	print "$_\n";
	next unless /^(.*)\/$/;
	my $odbcnode=$key->{$1};
	print "    " . join("\n    ", keys %$odbcnode) . "\n";
}

Open in new window

Suhas .Senior QA Manager
CERTIFIED EXPERT

Commented:
since the registry contents are stored in the form of key valyue pairs...
you need to use hashes... to access any entry.
 

Author

Commented:
Bu the constraint here is that I need to use eval to load the win32 module dynamically.
This is part of a code that will be used in both  unix and windows.
Explicitly loading irrespective of platform causes the code to fail in unix - loading via 'eval' causes this particular piece to fail in windows.
Top Expert 2009

Commented:
You could load the module through require, which is similar to use but processed at runtime instead of compile time.
You probably would also be better using $^O to determine if you are on windows.

if($^O eq 'MSWin32') {
    require Win32::TieRegistry;
    #Do whatever here with registry
}
else {
    #Non windows, do whatever
}
 
 
#Or, if you want to use the success/failure of loading Win32::TieRegistry:
eval {
    require Win32::TieRegistry;
    #Do whatever here with registry
};
if($@) {
    #There was an error
}

Open in new window

Author

Commented:
I have tried usnig eval - please refer to code sample in the question.
And that is what is not working.

If I use 'use' to load at compile time - there are no issues;however it restricts my abilities on unix.

Will it be possible to make the same work with 'eval'?
I do not get any exception during load of win32::TieRegistry,however the registry hit fails with a 'System cannot find the file'
Top Expert 2009

Commented:

The require would be more efficient than the eval with a string using 'use', but if this doesn't bother you, then the eval like you have is fine.

Does the code in post 24815323 work?  I tested it, and it worked on my windows computer fine.  What about if you don't remove the trailing slash from the key name?  Instead of this:
    foreach (@members){
        print "$_\n";
        next unless /^(.*)\/$/;
        my $odbcnode=$key->{$1};
        print "    " . join("\n    ", keys %$odbcnode) . "\n";
    }
Try this:
    foreach (@members){
        print "$_\n";
        next unless /^(.*)\/$/;
        my $odbcnode=$key->{$_};
        print "    " . join("\n    ", keys %$odbcnode) . "\n";
    }

Author

Commented:
No.none is working - they all give compilation/runtime errors

What I am trying now:
my $key="";

my regErr="";
$osType = get_osType();     # get the OS type
if($osType eq "WIN")
{
      require Win32::TieRegistry;
      import Win32::TieRegistry;
      $Registry->Delimiter("/");
      $key = $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/ODBC/ODBC.INI/"} or $regErr="ERROR , $^E\n";
      DEBUG(" open odbc  registry  node: $regErr \n");
}

Then I used the 'key' within a sub.
sub getDBConnect()
{
....
.....
if($osType eq "WIN")
{
my @members=keys( %{$key} );
foreach (@members){
if (m/^(.*)\/$/) {
.....
.....
}
}
}

This never works - am yet to find what the problem is .
However,if I  do the following - everything works like a song
use Win32::TieRegsitry;
$Registry->Delimiter("/");

And then within my sub:
sub getDBConnect()
{
my key="";
....
.....
if($osType eq "WIN")
{
$key = $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/ODBC/ODBC.INI/"} or $regErr="ERROR , $^E\n";
DEBUG(" open odbc  registry  node: $regErr \n");
my @members=keys( %{$key} );
foreach (@members){
if (m/^(.*)\/$/) {
.....
.....
}
}
}

Author

Commented:
What i do find is that it gives
Global symbol '$Registry' requires explicit package name - in the case where i use 'require'.
Suhas .Senior QA Manager
CERTIFIED EXPERT

Commented:
can you try by placing the require Win32::TieRegistry; at first line of the program...

Author

Commented:
Its all the same - the moment i shift from use win32::TieRegistry to
if($osType eq "WIN")
{
      require Win32::TieRegistry;
      import Win32::TieRegistry;
      $Registry->Delimiter("/");
}
I get symbol resolution erros for $Registry
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
Top Expert 2009

Commented:
Sorry, forgot to add that with require, you need to call the import to get the $Registry variable.
    require Win32::TieRegistry;
    Win32::TieRegistry->import();

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.