windows - Kontroller registreringsversion ved hjælp af Perl

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg skal gå til registreringsdatabasen og tjekke en programmeret installeret version. Jeg bruger perl til en hel del andre ting, men registret kontrol del er ikke at arbejde. Programversionen skal være 9,7 og op, så det kunne være 9.8 eller 9.7.5.


Når jeg installerer programmet viser det 9.7.4, men jeg skal bare bruge 9.7 til at blive kontrolleret.


Bellow er jeg på vej til DisplayVersion, som er en REG\_SZ, der viser 9.7.4.


ELLER


Jeg kunne bruge VersionMajor og VersionMinor sammen, hvilket er en REG\_DWORD. Som for Major er 9 og Minor er 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/)


Dette virker ikke, jeg kunne gøre det 9.200 og det virker stadig. Jeg forsøgte at bruge dette i stedet, og det ville stadig ikke fungere. Denne næste del forudsætter, at en ny klient skal installeres, hvis den går fra 9,7. Jeg forsøgte at bruge Great end eller lig med, men det virkede ikke.


$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/))


Enhver hjælp til at gøre dette korrekt eller fastsætte, hvad jeg laver.

Bedste reference


Flere ting:



  • Du nævner det ikke, men bruger du Perl-modulet Win32 :: TieRegistry? Hvis ikke, skal du. Det vil gøre håndteringen af ​​Windows-registreringsdatabasen meget nemmere. [34]

  • I Perl-dokumentationen kan du se på Version String under Scalar Value Constructors. Dette vil gøre manipulering af versionsstrengene meget, meget nemmere. Versionsstrenge har enten mere end en decimaltal i dem, eller begynder med brevet v. Jeg prefixer dem altid med v for at gøre det klart, hvad det er. [35] [36]



Her er et prøveprogram nedenfor, der viser dig, hvordan de kan bruges i sammenligninger:


#! /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
), $version, $testVersion;
    }
    else {
        printf qq(Version \%vd is less than test \%vd
), $version, $testVersion;
    }
}


Bemærk at jeg ikke kan udskrive versionsstrenger. Jeg skal bruge printf og sprintf og bruge formatet \%vd vektor decimalt til at udskrive dem. version strenge via en regelmæssig print erklæring kan forårsage alle former for kaos, da de virkelig er unicode repræsentationer. Du lægger dem i en udskrivningserklæring, og du ved ikke hvad du får.


Bemærk også, at du ikke sætter citater rundt om dem! Ellers vil du bare lave dem regelmæssige strenge.





NYT SVAR



Jeg forsøgte at finde en måde at konvertere en streng til en v-streng uden at downloade en valgfri pakke som Perl :: Version eller (Version), og jeg læste pludselig, at v-strings er udskrevet, og jeg vil ikke bruge en udskrevet funktion. [37]


Så lad os prøve noget andet ...


Vi kunne simpelthen dele op versionsnumre i deres bestanddele som arrays:


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


Ved at bruge følgende bit kode:


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


Nu kan vi hver del af versionsstrengen mod den anden. I ovenstående eksempel sammenligner jeg @versions 9 med @version 9, osv. Hvis @version var 9.6 ville jeg have sammenlignet 6]] i @version imod 7 i @minVersion og hurtigt opdaget at @minVersion er et højere versionsnummer. Imidlertid er i begge de to dele 7. Jeg kigger derefter på det tredje afsnit. Ups! @minVersion består af kun to sektioner. Således er @version større.


Her er en subrutine, der gør sammenligningen. Bemærk at jeg også verificerer, at hver sektion er et helt tal via reguleringsudtrykket /^d+$/. Min subrutine kan returnere fire værdier:



  • 0: Begge er af samme størrelse

  • 1: Første nummer er større

  • 2: Andet nummer er større

  • undef: Der er noget galt.



Her er programmet:


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!
";
}
elsif ($result == 0) {
print "$minVersion and $userVersion are the same
";
}
elsif ($result == 1) {
print "$minVersion is bigger than $userVersion
";
}
elsif ($result == 2) {
print "$userVersion is bigger than $minVersion
";
}
else {
print "Something is wrong
";
}


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;
    }
}
}

Andre referencer 1


Brug Win32 :: TieRegistry



Du sagde i dit svar, at du ikke brugte Win32::TieRegistry. Jeg vil bare vise dig, hvad det kan gøre for læsbarheden af ​​dit program:


Din vej



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


Med 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);


Eller du kan opdele det:


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


Se hvor meget lettere det er at læse. Du kan også bruge dette til at teste nøgler også.


( Word 'o Advarsel : Jeg har ikke en Windows-maskine foran mig, så jeg har ikke nøjagtigt kontrolleret kodenes gyldighed. Prøv at lege med det og se hvad du får.)