reading windows regsitry with perl

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
ranadhirAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Suhas .QA ManagerCommented:
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

0
ranadhirAuthor Commented:
dont you need to declare the 'Registry' variable?
0
Suhas .QA ManagerCommented:
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
0
Newly released Acronis True Image 2019

In announcing the release of the 15th Anniversary Edition of Acronis True Image 2019, the company revealed that its artificial intelligence-based anti-ransomware technology – stopped more than 200,000 ransomware attacks on 150,000 customers last year.

ranadhirAuthor 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
}
0
Adam314Commented:

#!/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

0
Suhas .QA ManagerCommented:
since the registry contents are stored in the form of key valyue pairs...
you need to use hashes... to access any entry.
 
0
ranadhirAuthor 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.
0
Adam314Commented:
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

0
ranadhirAuthor 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'
0
Adam314Commented:

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";
    }
0
ranadhirAuthor 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/^(.*)\/$/) {
.....
.....
}
}
}

0
ranadhirAuthor Commented:
What i do find is that it gives
Global symbol '$Registry' requires explicit package name - in the case where i use 'require'.
0
Suhas .QA ManagerCommented:
can you try by placing the require Win32::TieRegistry; at first line of the program...
0
ranadhirAuthor 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
0
ranadhirAuthor Commented:
l will use the fully qualified name now -$Win32::TieRegistry::Registry
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Adam314Commented:
Sorry, forgot to add that with require, you need to call the import to get the $Registry variable.
    require Win32::TieRegistry;
    Win32::TieRegistry->import();

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Perl

From novice to tech pro — start learning today.