MarkBe

[SOLVED] Registry check function

12 posts in this topic

#1 ·  Posted (edited)

Hi

I am trying to check a number of applications are up to date and install the update if required. This will run as a shutdown script, pushed out through Group Policy.

I am querying various registry keys to determine if

  1. The software is actually installed
  2. The software is at the correct version

Once the need for update is determined then it calls another function to run the update.

If the software is up to date or not installed, it moves down to the next software section which changes the registry key variables and calls the registry query function again

I have managed to get the function for (un)installs to work but I am having trouble with the registry query function

#NoTrayIcon
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>
#include <FileConstants.au3>

; Here we go!
;##########################################################################################################

;Declare variables
Global $RegKey86, $RegKey64, $RegValueName, $RegValueData, $CheckVersion86, $CheckVersion64


; 7Zip
;##########################################################################################################
_7Zip_Function()
Func _7Zip_Function()

; Registry location and values that are checked for current software version
; Ensure the x64 key is preceeded with 'HKLM64'
$RegKey86="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip"
$RegKey64="HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip"
$RegValueName="DisplayVersion"
$RegValueData="16.04"

; Excecution
; ---------------------------------------------------------------------------------------------------------

If _CheckSW() = 1 Then
        _UninstallOldVer()
        _InstallSW()
    EndIf
EndFunc ;==>_7Zip_Function


; Functions
;##########################################################################################################
Func _CheckSW()
    $CheckVersion86=RegRead ($RegKey86, $RegValueName)
    $CheckVersion64=RegRead ($RegKey64, $RegValueName)
    If $CheckVersion86=$RegValueData Or $CheckVersion64=$RegValueData Then
        Return 0
    ElseIf $CheckVersion86="" And $CheckVersion64="" Then
        Return 0
    Else
        Return 1
    EndIf
EndFunc ;==>CheckSW

 

Edited by MarkBe
Solved

Share this post


Link to post
Share on other sites



#2 ·  Posted

What trouble are you having?  Personally I would use _VersionCompare something like:

#NoTrayIcon
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>
#include <FileConstants.au3>
#include <Misc.au3>

; Here we go!
;##########################################################################################################

;Declare variables
Global $RegKey86, $RegKey64, $RegValueName, $RegValueData, $CheckVersion86, $CheckVersion64

; 7Zip
;##########################################################################################################
_7Zip_Function()
Func _7Zip_Function()

; Registry location and values that are checked for current software version
; Ensure the x64 key is preceeded with 'HKLM64'
    $RegKey86="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip"
    $RegKey64="HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip"
    $RegValueName="DisplayVersion"
    $RegValueData="16.04"

; Excecution
; ---------------------------------------------------------------------------------------------------------
    If _RegVersionCompare($RegKey64, $RegValueName, $RegValueData) = 1 Then
        _UninstallOldVer()
        _InstallSW()
    EndIf
EndFunc ;==>_7Zip_Function

; Functions
;##########################################################################################################
Func _RegVersionCompare($sRegHive, $sRegKey, $sRegValue)
    Local $iVersionCompare = _VersionCompare(RegRead($sRegHive, $sRegKey), $sRegValue)
    Switch $iVersionCompare
        Case 0
            Return 0
        Case 1
            Return 0
        Case -1
            Return 1
    EndSwitch
EndFunc ;==>CheckSW

 

1 person likes this

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Thanks Subz

This is very close. Once I had put in #include <Misc.au3> it runs the installer if the software is out of date and does not run the installer if it is current.

There is one scenario that isn't working quite right for me yet, if the software isn't installed at all, I don't want the installer to run. Do you have a suggestion for handling that?

Thanks

p.s. I like the fact that if someone has manually installed a newer version that the script you suggested doesn't roll it back

Edited by MarkBe
p.s.

Share this post


Link to post
Share on other sites

#4 ·  Posted

You could use the following:

Func _RegVersionCompare($sRegHive, $sRegKey, $sRegValue)
    If RegRead($sRegHive, $sRegKey) = "" Then Return 0
    Local $iVersionCompare = _VersionCompare(RegRead($sRegHive, $sRegKey), $sRegValue)
    Switch $iVersionCompare
        Case 0
            Return 0
        Case 1
            Return 0
        Case -1
            Return 1
    EndSwitch
EndFunc ;==>CheckSW

 

Share this post


Link to post
Share on other sites

#5 ·  Posted

Thanks Subz

You have pointed me in the right direction. Unfortunately the old version of 7Zip I am updating stores the version in a different hive ... I'll try and fix this new development myself and post back if I get stuck again

Now I just need to work out how to mark your reply as the answer ...

Share this post


Link to post
Share on other sites

#6 ·  Posted

They only have the Like this buttons on each post, if you want to mark the post as resolved, you can edit the first post which allows you to edit the title of the post.

Share this post


Link to post
Share on other sites

#7 ·  Posted

There's probably a more elegant way to do this but I ended up with the following:

#NoTrayIcon
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>
#include <FileConstants.au3>
#include <Misc.au3>

; Here we go!
;##########################################################################################################

;Declare variables
Global $RegHive86, $RegHive64, $RegKey, $RegValue, $OldVerRegHive86, $OldVerRegHive64, $OldVerRegHive86on64, $OldVerRegVerString, $OldVerRegVerValue, $OldVerUninstallStringx86, $OldVerUninstallStringx64

; 7Zip
;##########################################################################################################
_7Zip_Function()
Func _7Zip_Function()

; Variables
; ---------------------------------------------------------------------------------------------------------
; Registry location and values that are checked for current software version. Don't use paths with hash values
; Ensure the x64 key is preceeded with 'HKLM64'
$RegHive86="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip"
$RegHive64="HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip"
$RegKey="DisplayVersion"
$RegValue="16.04"

; Reg keys and values that are checked for old versions
$OldVerRegHive86="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{23170F69-40C1-2701-0920-000001000000}"
$OldVerRegHive64="HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{23170F69-40C1-2702-0920-000001000000}"
$OldVerRegHive86on64="HKLM64\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{23170F69-40C1-2701-0920-000001000000}"

    If _RegVersionCompare($RegHive64, $RegHive86, $OldVerRegHive64, $OldVerRegHive86, $OldVerRegHive86on64, $RegKey, $RegValue) = 1 Then
        _UninstallOldVer()
        _InstallSW()
    EndIf
EndFunc ;==>_7Zip_Function


; Functions
;##########################################################################################################
Func _RegVersionCompare($sRegHive64, $sRegHive86, $sOldVerRegHive64, $sOldVerRegHive86, $sOldVerRegHive86on64, $sRegKey, $sRegValue)
    If Not RegRead($sRegHive64, $sRegKey) = "" Then
        Local $iVersionCompare = _VersionCompare(RegRead($sRegHive64, $sRegKey), $sRegValue)
        Switch $iVersionCompare
            Case 0
                Return 0
            Case 1
                Return 0
            Case -1
                Return 1
        EndSwitch
    ElseIf Not RegRead($sRegHive86, $sRegKey) = "" Then
        Local $iVersionCompare = _VersionCompare(RegRead($sRegHive86, $sRegKey), $sRegValue)
        Switch $iVersionCompare
            Case 0
                Return 0
            Case 1
                Return 0
            Case -1
                Return 1
        EndSwitch
    ElseIf Not RegRead($sOldVerRegHive64, $sRegKey) = "" Then
        Return 1
    ElseIf Not RegRead($sOldVerRegHive86, $sRegKey) = "" Then
        Return 1
    ElseIf Not RegRead($sOldVerRegHive86on64, $sRegKey) = "" Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc ;==>_RegVersionCompare

 

Share this post


Link to post
Share on other sites

#8 ·  Posted

Couple of things to note:

$OldVerRegHive86 = $OldVerRegHive86on64
- HKLM on a x64 system accesses 32 bit hive i.e. HKLM\Software\Wow6432Node

Since x64 and x86 versions of 7-zip are different installers you should specify which version to install using @OSArch macro, you may also need to get the Guids for both x86/x64 to uninstall for example:

  • "{23170F69-40C1-2701-0920-000001000000}" ; 7-Zip 9.20 x86 Msi Version
  • "{23170F69-40C1-2702-0920-000001000000}" ; 7-Zip 9.20 x64 Msi Version
  • "{23170F69-40C1-2701-1604-000001000000}" ; 7-Zip 16.04 x86 Msi Version
  • "{23170F69-40C1-2702-1604-000001000000}" ; 7-Zip 16.04 x64 Msi Version

Share this post


Link to post
Share on other sites

#9 ·  Posted

Yes, discovered that the hard way - last time I deployed this using a batch script

What I have in that section for 7Zip is

#NoTrayIcon
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>
#include <FileConstants.au3>
#include <Misc.au3>

$SoftwareName="7Zip Archiver"
$SoftwareVersion="16.04"
$InstallingUpdateMessage="Updating " & $SoftwareName & " to " & $SoftwareVersion & "."
$EndMessage="The current version of " & $SoftwareName & " is now installed."
$FailMessage=$SoftwareName & " update failed to install. Please report error to your local IT department."
$UninstallingOldMessage="Uninstalling old versions of " & $SoftwareName & "."

; Paths and files (Don't forget the "\" at the end of the path)==> \\Servername\Share\
$SourcePath="\\domain\dfsroot\share\7Zip\"
$WorkingDirectory="C:\InstallCache\7zip\"
$x86Installer="7z1604.exe"
$x64Installer="7z1604x64.exe"
$SWInstaller=((@OSArch = "X86") ? $x86Installer : $x64Installer)
$InstallerSwitches=" /S"

_InstallSW()
Func _InstallSW()
    MsgBox ($MB_ICONINFORMATION, "Installing", $InstallingUpdateMessage, 3)
    FileCopy ($SourcePath & $SWInstaller, $WorkingDirectory & $SWInstaller, $FC_OVERWRITE + $FC_CREATEPATH)
    If StringLower(StringRight($SWInstaller, 4))=".exe" Then
        RunWait (@ComSpec & ' /k START "' & $SoftwareName & ' Installer" /wait "' & $WorkingDirectory & $SWInstaller & '"' & $InstallerSwitches & ' && EXIT', @SystemDir, @SW_HIDE)
    Else
        RunWait ('msiexec /i "' & $WorkingDirectory & $SWInstaller & '"' & $InstallerSwitches, @SystemDir)
    EndIf
EndFunc ;==>InstallSW

 

Share this post


Link to post
Share on other sites

#10 ·  Posted

You should be able to run the install directly from the domain share, but if you wish to copy, I would probably place an "If FileExists" so that it doesn't copy down everytime, I would also use SplashTextOn function to display the progress of the install.  Not sure why you need cmd to run the exe you should be able to just run it directly from the Working directory using RunWait.  Lastly not sure what the last Runwait ('msiexe /i... is suppose to do :)

Share this post


Link to post
Share on other sites

#11 ·  Posted

2 minutes ago, Subz said:

You should be able to run the install directly from the domain share, but if you wish to copy, I would probably place an "If FileExists" so that it doesn't copy down everytime, I would also use SplashTextOn function to display the progress of the install.  Not sure why you need cmd to run the exe you should be able to just run it directly from the Working directory using RunWait.  Lastly not sure what the last Runwait ('msiexe /i... is suppose to do :)

I used to run the installers from the domain share but some remote users found that the script timed out before completion

I also decided to replace on copy because some users got a corrupted copy on the C:\ and so I needed the EXE to be replaced so it didn't fail repetitively! There are some awful network connections between the servers and some of my users - being addressed at the moment though :-)

SplashTextOn sounds good. I haven't discovered many of the cool features of AutoIT yet ... I'm a bit of a noob!

This was taken all from a RunAsWait so I needed to plug in credentials to elevate. Not sure why I used CMD ... think it was because I used to do all the grunt work with CMD and just use AutoIT to elevate. Ran into problems (x64 v x86 batch) so decided to learn AutoIT.

Lastly, I have the msiexec in the function so that if, in the next software section the installer is an MSI then I can still call the same _InstallSW() function and just pipe in different variables

Share this post


Link to post
Share on other sites

#12 ·  Posted

definitely cleaner:

Func _InstallSW()
    MsgBox ($MB_ICONINFORMATION, "Installing", $InstallingUpdateMessage, 3)
    FileCopy ($SourcePath & $SWInstaller, $WorkingDirectory & $SWInstaller, $FC_OVERWRITE + $FC_CREATEPATH)
    If StringLower(StringRight($SWInstaller, 4))=".exe" Then
        RunWait ('"' & $WorkingDirectory & $SWInstaller & '"' & $InstallerSwitches)
    Else
        RunWait ('msiexec /i "' & $WorkingDirectory & $SWInstaller & '"' & $InstallerSwitches)
    EndIf
EndFunc ;==>InstallSW

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • mati
      By mati
      Hi,
      I wonder if
      AutoIt3Wrapper_run_debug_mode = Y can include run information about functions which are called within the main code. So far I noticed in the console that the function itself is called but no specific run information from  inside the function is provided. Is there a chance to show the entire debug log including functions in the console?
      I furthermore noticed a stop of information when a loop is entered. What could be the reason for that?
       
      Thanks for help.
    • TrashBoat
      By TrashBoat
      Is this possible:
      Executing a function from an include, but taking the function name from a gui input and then executing that function using the include:
      #include <Something.au3> ;input reads "Tree" $functionName = GuiCtrlRead($input1) $functionName(1) And the include is gonna have
      Func Tree($x) If $x = 1 Then $this = "text" MsgBox(0,$this,"whatever") EndFunc is it possible?
    • hcI
      By hcI
      Hello, i'm making a little script that lets users enter a question and if the script can't answer to, it ask what would be the answer (a bit like siri on IPhones). And I try to display the "supposed array" I still have an error.. I searched on Google and got nothing looked in the help file too.. I'm here to know if someone have a solution to my error please.
      Here is where $a and $b should become arrays :
      Dim $dossier = @AppDataDir & "\Siri2" Dim $chemin = $dossier & "\data.ini" Global $a = _InfoRead($chemin, 0) Global $b = _InfoRead($chemin, 1) with this function :
      Func _InfoRead($path, $mode = 0) If DirGetSize($dossier) = -1 Then Return SetError(-4) If Not FileExists($chemin) Then Return SetError(-5) Local $readed = IniReadSection($path, "data") If @error Then Return SetError(-3) $size = $readed[0][0] Local $return[$size] For $i = 1 To $size Step 1 $return[$i - 1] = $readed[$i][$mode] Next Return $return EndFunc and the thing that i don't understand is that, after _InfoRead return affected to $a, I can't use _ArrayDisplay because of  error 1 "$aArray is not an array" (and same fpr the variable $b)..
      Can please someone help me to understand why is it doing this ?

      -hcI
    • kawliga751
      By kawliga751
      I'm new to Auotit but I have built a simple script that "runs" a different "batch" file based on certain days of the workweek. The script works now, but I was wanting to eliminate the need for a manual date entry. For example "First Batch' needs to run every Tuesday thru Thursday however "Second Batch" needs to run only on Friday and "Third Batch" needs to run only on Monday. In addition the 1st batch file runs on Tuesday, say 06/06 (the "FW" section) but then needs to actually report (the F4 date) the next weekday so this Batch actually needs 2 dates verified. 
      What I'm trying to do is when the script is initiated it gets the date, verifies if and which weekday it is and in turn goes to and runs the appropriate "Batch' file.  
      I've found ways to verify weekdays but can't find anything to do all of the above.
      Any help is MUCH appreciated.
       
      ;P10
      ShellExecute("C:\Program Files (x86)\Ericom Software\PowerTerm Enterprise\Sessions\mir00p10.PTS")

      WinWait('(A) Soutwest P10 : PowerTerm Pro Enterprise Suite')
      WinActivate('(A) Soutwest P10 : PowerTerm Pro Enterprise Suite')
      Send('$Login)
      Sleep(3000)
      Send('{Enter}')
      Sleep(3000)
      Send($Password)
      Send('{Enter}')
      Sleep(3000)
      ; ****First Batch file run
      Send('Batch')
      Sleep(3000)
      Send('{Enter}')
      Send('FW')
      Send('{Enter}')
      Send('{DOWN}')
      Send($Date)
      Send('{Enter}')
      Send('{Enter}')
      Send($Date)
      Send('{F9}')
      Send('Y')
      Sleep(3000)
      Send('{Enter}')
      Send('{F4}')
      Send('Y')
      Sleep(3000)
      Send('{Enter}')
      Send($Date)
      Send('{Enter}')
      Send('0620')
      Send('{Enter}')
      SEND('{!}SW0410PM.FWR')
      Send('{Enter}')
      Sleep(3000)
      Send('Y')
      Send('{Enter}')
      Sleep(3000)
      Send('{F9}')
      Sleep(3000)
      ; ****Second Batch file run
      Send('Batch')
      Sleep(3000)
      Send('{Enter}')
      Send('FW')
      Send('{Enter}')
      Send('{DOWN}')
      Send($Date)
      Send('{Enter}')
      Send('{Enter}')
      Send($Date)
      Send('{F9}')
      Send('Y')
      Sleep(3000)
      Send('{Enter}')
      Send('{F4}')
      Send('Y')
      Sleep(3000)
      Send('{Enter}')
      Send($Date)
      Send('{Enter}')
      Send('0620')
      Send('{Enter}')
      SEND('{!}SO0411AM.FWR')
      Send('{Enter}')
      Sleep(3000)
      Send('Y')
      Send('{Enter}')
      Sleep(3000)
      Send('{F9}')
      Sleep(3000)
      ; ****Third Batch file run
      Send('Batch')
      Sleep(3000)
      Send('{Enter}')
      Send('FW')
      Send('{Enter}')
      Send('{DOWN}')
      Send($Date)
      Send('{Enter}')
      Send('{Enter}')
      Send($Date)
      Send('{F9}')
      Send('Y')
      Sleep(3000)
      Send('{Enter}')
      Send('{F4}')
      Send('Y')
      Sleep(3000)
      Send('{Enter}')
      Send($Date)
      Send('{Enter}')
      Send('0620')
      Send('{Enter}')
      SEND('{!}SW0411AM.LOA')
      Send('{Enter}')
      Sleep(3000)
      Send('Y')
      Send('{Enter}')
      Sleep(3000)
      Send('{F9}')
      Sleep(3000)
      Send('EXIT')
       
       
    • steveeye
      By steveeye
      Hi, can anybody explain "pure virtual function" and how to make use of them?