开发者

Check Registry Version using Perl

开发者 https://www.devze.com 2023-04-01 19:25 出处:网络
I need to go to the registry and check a programs installed version. I am using perl to a whole lot of others things but the registry checking part isn\'t working. The program version has to be 9.7 an

I need to go to the registry and check a programs installed version. I am using perl to a whole lot of others things but the registry checking part isn't working. The program version has to be 9.7 and up so it could be 9.8 or 9.7.5.

When I install the program it shows 9.7.4 but I just need the 9.7 to be checked.

Bellow is me going to DisplayVersion which is a REG_SZ which shows 9.7.4开发者_StackOverflow社区.

OR

I could use VersionMajor and VersionMinor together which is a REG_DWORD. Which for Major is 9 and Minor is 7.

$ProgVersion= `$rootpath\\system32\\reg\.exe query \\\\$ASSET\\HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{9ACB414D-9347-40B6-A453-5EFB2DB59DFA} \/v DisplayVersion`;  

if ($ProgVersion == /9.7/)

This doesn't work I could make it 9.200 and it still works. I tried to use this instead and it still wouldn't work. This next part is assuming that a new client needs to be install if it goes from 9.7. I was trying to use Great than or equal to, but it didn't work.

$ProgVersionMajor= `$rootpath\\system32\\reg\.exe query \\\\$ASSET\\HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{9ACB414D-9347-40B6-A453-5EFB2DB59DFA} \/v VersionMajor`;  

$ProgVersionMinor= `$rootpath\\system32\\reg\.exe query \\\\$ASSET\\HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{9ACB414D-9347-40B6-A453-5EFB2DB59DFA} \/v VersionMinor`;  

if (($ProgVersionMajor=~ /9/) && ($ProgVersionMinor=~ /7/))

Any help on doing this correctly or fixing what I am doing.


Several things:

  • You don't mention it, but are you using the Perl module Win32::TieRegistry? If not, you should. It'll make handling the Windows registry much easier.

  • In the Perl documentation, you can look at Version String under Scalar Value Constructors. This will make manipulating version strings much, much easier. Version strings have either more than one decimal place in them, or start with the letter v. I always prefix them with v to make it obvious what it is.

Here's a sample program below showing you how they can be used in comparisons:

#! /usr/bin/env perl
#

use strict;
use warnings;

my $version = v4.10.3;

for my $testVersion (v3.5.2, v4.4.1, v5.0.1) {
    if ($version gt $testVersion) {
        printf qq(Version %vd is greater than test %vd\n), $version, $testVersion;
    }
    else {
        printf qq(Version %vd is less than test %vd\n), $version, $testVersion;
    }
}

Note that I can't just print version strings. I have to use printf and sprintf and use the %vd vector decimal format to print them out. Printing version strings via a regular print statement can cause all sorts of havoc since they're really unicode representations. You put them in a print statement and you don't know what you're getting.

Also notice that you do not put quotes around them! Otherwise, you'll just make them regular strings.


NEW ANSWER

I was trying to find a way to convert a string into a v-string without downloading an optional package like Perl::Version or (Version), and I suddenly read that v-strings are deprecated, and I don't want to use a deprecated feature.

So, let's try something else...

We could simply divide up version numbers into their constituent components as arrays:

v1.2.3 => $version[0] = 1, $version[1] = 2, $version[2] = 3

By using the following bit of code:

my @version = split /\./, "9.7.5";
my @minVersion = split /\./, "9.7"

Now, we can each part of the version string against the other. In the above example, I compare the 9 of @version with the 9 of @version, etc. If @version was 9.6 I would have compared the 6 in @version against the 7 in @minVersion and quickly discovered that @minVersion is a higher version number. However, in both the second parts are 7. I then look at the third section. Whoops! @minVersion consists of only two sections. Thus, @version is bigger.

Here's a subroutine that does the comparison. Note that I also verify that each section is an integer via the /^\d+$/ regular expression. My subroutine can return four values:

  • 0: Both are the same size
  • 1: First Number is bigger
  • 2: Second Number is bigger
  • undef: There is something wrong.

Here's the program:

my $minVersion  = "10.3.1.3";
my $userVersion = "10.3.2";

# Create the version arrays

my $result = compare($minVersion, $userVersion);

if (not defined $results) {
    print "Non-version string detected!\n";
}
elsif ($result == 0) {
print "$minVersion and $userVersion are the same\n";
}
elsif ($result == 1) {
print "$minVersion is bigger than $userVersion\n";
}
elsif ($result == 2) {
print "$userVersion is bigger than $minVersion\n";
}
else {
print "Something is wrong\n";
}


sub compare {

my $version1 = shift;
my $version2 = shift;

my @versionList1 = split /\./, $version1;
my @versionList2 = split /\./, $version2;

my $result;

while (1) {

    # Shift off the first value for comparison
    # Returns undef if there are no more values to parse

    my $versionCompare1 = shift @versionList1;
    my $versionCompare2 = shift @versionList2;

    # If both are empty, Versions Matched

    if (not defined $versionCompare1 and not defined $versionCompare2) {
    return 0;
    }

    # If $versionCompare1 is empty $version2 is bigger
    if (not defined $versionCompare1) {
    return 2;
    }
    # If $versionCompare2 is empty $version1 is bigger
    if (not defined $versionCompare2) {
    return 1;
    }
    
    # Make sure both are numeric or else there's an error
    if ($versionCompare1 !~ /\^d+$/ or $versionCompare2 !~ /\^\d+$/) {
    return;
    }

    if ($versionCompare1 > $versionCompare2) {
    return 1;
    }
    if ($versionCompare2 > $versionCompare1) {
    return 2;
    }
}
}


Using Win32::TieRegistry

You said in your answer you didn't use Win32::TieRegistry. I just want to show you what it can do for the readability of your program:

Your Way

$ProgVersion= `$rootpath\\system32\\reg\.exe query \\\\$ASSET\\HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{9ACB414D-9347-40B6-A453-5EFB2DB59DFA} \/v DisplayVersion`;

With Win32::TieRegistry

use Win32::TieRegistry ( TiedHash => '%RegHash', DWordsToHex => 0 );

my $key = $TiedHash->{LMachine}->{Software}->{Wow6432Node}->{Microsoft}->{Windows}->{CurrentVersion}->{Uninstall}->{9ACB414D-9347-40B6-A453-5EFB2DB59DFA}->{Version};
my $programValue = $key->GetValue;
my $stringValue = unpack("L", $programValue);

Or, you can split it up:

my $MSSoftware = $TiedHash->{LMachine}->{Software}->{Wow6432Node}->{Microsoft};
my $uninstall = $MSSoftware->{Windows}->{CurrentVersion}->{Uninstall};
my $programVersion = $uninstall->{9ACB414D-9347-40B6-A453-5EFB2DB59DFA}->{Version};

See how much easier that's to read. You can also use this to test keys too.

(Word 'o Warning: I don't have a Windows machine in front of me, so I didn't exactly check the validity of the code. Try playing around with it and see what you get.)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号