Rob van der Woude's Scripting Pages

Help for UpdateCheck.hta, version 1.40

UpdateCheck.hta checks installed versions and latest available versions for several programs, and presents a download button for each program where these versions don't match.

The programs to be checked are listed in UpdateCheck's helper INI file UpdateCheck.ini.
This INI file also tells UpdateCheck.hta which version check techniques should be used for each program.

When UpdateCheck.hta is started, it first checks if the INI file is found in its own parent folder.
If not, it will download the default INI file from the website. Downloading the default INI file can also be forced by clicking the "Update Program List" button.

Next, it will read the list of programs from the INI file, and list them in the table in the program window.
For each listed program, the installed version is determined, using the technique specified for that program in the INI file.

Note: Depending on the number of programs and especially on the techniques used to determine the version, this may take from a couple of seconds up to several minutes!

When the installed versions for all programs are checked, the versions are listed in the table in the program window.

If a program's version could not be determined, the program is assumed not to be installed.
In that case, the checkbox for the program will be unchecked, and a variable will be set telling UpdateCheck.hta that a change has been made.
Upon closing UpdateCheck.hta, or when clicking the "Save Changes" button, if this variable was set, a popup message will appear, asking you if you want to save the changes.

Confirm removal from the list

By clicking the "Save Changes" button, only the selected programs will be written to the new INI file — after confirmation that you do want to remove the unchecked programs.

Confirm removal from the list

You can also manually remove programs from the INI file by deselecting their checkboxes and then save the changes.

Note: Each time the INI file is changed or replaced, a copy of the current INI file will be stored for backup purposes.
The copy will be renamed UpdateCheck.ini.version.backup.timestamp, e.g. UpdateCheck.ini.1.40.backup.20240328095911

Next, UpdateCheck.hta will determine the latest available versions on the web, and display the results. This may take a while!
If the installed version of a program doesn't match the latest available version, a download button is placed at the end of the program's table row.

Note: By clicking the "Show All Downloads" button, the download buttons for every program will be available.

You can manually remove a program from the list by deselecting its checkbox, or reinsert a program listed as "Not installed" by reselecting its checkbox.
Click the "Save Changes" button to make the changes permanent, or click "Yes" when prompted to save the changes when closing UpdateCheck.hta.
You may want to click the "Rescan Programs" button to run a new scan, testing the modified INI file.

As of version 1.30, UpdateCheck's INI file contains entries to check the HTA and INI versions for updates.

If an update for the HTA is available, a button with caption "Install" will be available.
If you click it, the HTA will download the ZIPped update, extract it into its own parent folder (overwriting itself), and restart its new self.

If an update for the INI file is available, a button with caption "Update" will be available.
Clicking it is like clicking the "Update Program List" button: the default INI file will be downloaded from the website and loaded.
You will still need to click "Save Changes" to overwrite your current INI file.

Command Line Switches

The following command line switches are accepted by UpdateCheck.hta:

/BW Use black and white style for better contrast.
/DEBUG Opens a separate debug window, which can be used to trace the entire version detection process.
Use this switch when working on custom program list entries.
The content of the debug window will be saved automatically in a uniquely named log file when closing the HTA (file name UpdateCheck.Computername.YYYYMMDDhhmmss.log, located in UpdateCheck.hta's parent folder, e.g. UpdateCheck.mycomputer.20240328095911.log).
/DSWP Don't Save Web Pages (requires /DEBUG).
By default, when debugging, copies of the web pages used to retrieve the latest version are saved in UpdateCheck.hta's parent folder as UpdateCheck.GetLatestVersion.ProgID.YYYYMMDDhhmmss.html, e.g. UpdateCheck.GetLatestVersion.7ZIP.20240328095911.html; the /DSWP switch disables that feature.
/FORCE Display last available versions and download buttons for all programs, whether installed or not.
/HELP or /? Opens the UpdateCheck Help web page in the default browser.
/NOEDIT Do not show Edit buttons (to edit program entries in the INI file) while debugging, unless the installed or latest version could not be found.
/QUIET Run minimized, only prompt for action if updates are available.
/SIZE:widthXheight Set required window size, e.g. /SIZE:1024x768.
/SKIPDOWNGRADE Do not propose downgrades for programs that have a higher version than the one displayed on the manufacturer's website.
Use this switch combined with the /QUIET switch.
/SKIPNOTINSTALLED Do not display programs that are not installed (or not found), even if they are listed in the programs list.
/SKIPWMI While debugging, skip programs that require a WMI query to find the installed version (requires /DEBUG).
This switch is intended for testing only, it may shorten the time of a test run by as much as 90%.

Each command line argument can be made "permanent" by saving it in a plain ASCII text file named UpdateCheck.cfg, located in the HTA's parent folder.
The arguments may all be written as a single line, or each argument on its own line.

Customizing UpdateCheck.ini

Removing programs from the list by deselecting their checkboxes was discussed in the first section.
This paragraph will explain how to manually add a new program to the list.
It will use fake entries or refer to entries from the default INI file to demonstrate the various techniques.

Note: Before customizing the INI file, you may want to download the latest default INI file first.
Click the "Update Program List" button first, and the "Save Changes" button next.

Techniques

Several techniques can be used to determine a program's (installed) version:

  1. Read the version from the registry
  2. Read the executable's location from the registry and determine its file or product version
  3. Search the PATH for the executable and determine its file or product version
  4. Assume the executable's location and determine its file or product version
  5. Let the (command line) program return its own version
  6. Query WMI
Note: This table is ordered by descending performance: reading the registry is fast, querying WMI is notoriously slow.

1. & 2. Registry

Use the RegVersion parameter to read the version directly from the registry.
In case the registry key is located under HKEY_LOCAL_MACHINE\SOFTWARE use RegVersion2 to point at the alternative HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node (for 32-bit programs in 64-bit Windows).

If the specified registry key is terminated with a backslash, the default value for that key will be returned.
E.g. in the example above, HKEY_LOCAL_MACHINE\SOFTWARE\GPL Ghostscript\9.14\ would return an empty string (default value not set).

If the specified registry key is terminated with a backslash followed by an asterisk, the highest numbered subkey name will be returned.
E.g. in the example above, HKEY_LOCAL_MACHINE\SOFTWARE\GPL Ghostscript\* would return 9.14.

If the specified registry key contains an asterisk, the highest numbered match will be used.
E.g. in the example below, HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Opera *\Publisher would return Opera Software ASA.

To search for a DisplayVersion value in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall (or HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall), you may also use the INI parameter DisplayName. This parameter accepts a regular expression that must match the program's DisplayName value, e.g. DisplayName=Java \d+ Update \d+

Use ListProgs.bat or ListProgs.exe to list all registry keys that can be found with the DisplayName parameter.

 

The most common locations to look for a program's version are:

  1. The value of HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\product\DisplayVersion for 32-bit software in 32-bit Windows and 64-bit software in 64-bit Windows
  2. The value of HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\product\DisplayVersion for 32-bit software in 64-bit Windows
  3. Values or subkeys of HKEY_LOCAL_MACHINE\SOFTWARE\manufacturer\product for 32-bit software in 32-bit Windows and 64-bit software in 64-bit Windows
  4. Values or subkeys of HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\manufacturer\product for 32-bit software in 64-bit Windows
  5. Values or subkeys of HKEY_CURRENT_USER\Software\manufacturer\product

For registry location I. use RegVersion or DisplayName.
For registry location II. use RegVersion2 or DisplayName.
For III., IV. and V. try using RegVersion if a value or subkey contains the version, if not try RegPath if a value contains the absolute path to the executable, otherwise use both RegPath and Executable if all you can find is a value with part of the executable's path.
For registry locations III and IV also add RegVersion2 or Regpath2 (whichever is applicable) to support 64-bit Windows.

2. & 3. & 4. File or Product Version

If there are no registry values (or keys) available to determine the program version, try the executable's file or product version.

First check if any value is available to determine the executable's path.
If the full path to the executable is available in a registry value, use that in RegPath and RegPath2 and omit Executable and Executable2.

If not, try to find a value pointing to the executable's parent folder, or to a component or icon in a subfolder.
If a value is available, use it in RegPath and Regpath2, and specify the relative path from there to the executable in Executable (omit Executable2).

If no registry value can be used, and the executable is likely to be found in the PATH, use the SearchPATH parameter to tell the HTA to go find the executable in the PATH (i.e. SearchPATH=1).

If no registry value can be used, nor is the executable located in the PATH, then specify the absolute path to the excutable in Executable, and its 32/64-bit alternative path in Executable2.
Wherever possible, use environment variables %ProgramFiles% and %ProgramFiles(x86)% instead of C:\Program Files and C:\Program Files (x86), in case a different drive letter is used by Windows.
Likewise, use %WinDir% instead of C:\Windows or C:\WINNT.

Unless UseProductVersion is used, UpdateCheck.hta will display the executable's file version.
Use UseProductVersion only if the executable's file version and product version may be different, and only if your Windows system language is supported by UpdateCheck.hta (version 1.30 supports UseProductVersion for Dutch and English only).

Note: I will gladly add support for other languages, but I need your help to do that: download and run FileDetails.vbs, redirecting its output to a log file, and send me the file, and the language name in English (e.g. "French").

5. Command Line

If the registry and file version methods fail, and if the (command line!) executable is likely to be found in the %PATH% variable, you may try calling the command itself to get its program version.
Many command line programs will return, amongst others, their version when called with command line argument /? (or sometimes without a command line argument at all).
CommandLine tells UpdateCheck.hta what command to use.

Beware of problems with Unicode vs. ANSI output.
These problems may be averted by using CMD /A /C, e.g. CMD /A /C perl.exe -v
Some programs will send their help screen to Standard Error instead of Standard Output.
This won't be a problem if 2>&1 is used to merge Standard Error and Standard Output, e.g. CMD /A /C perl.exe -v 2>&1

The output of the command line program often requires filtering to extract the version only.
Use OutputGrep to specify a regular expression that will do the job.
OutputGrep is mandatory if CommandLine is used, so use .* for the regular expression if the command line returns the version only.

The main disadvantage of this method is that one can never be certain the executable's location will be in the %PATH% variable.

6. Query WMI

Use a WMI query only if you are desparate enough to wait for it to complete.

A query of the Win32_Product class in WMI's root/CIMV2 namespace returns a lot of information about (most of the) installed programs.
This info contains the program's version, and its installation path, if you're lucky.
Unfortunately, there is no way to tell if these properties will return any data or not, you'll just have to try.

And did I mention it is slow?
On my computer 40 non-WMI checks took 6 seconds, while 4 WMI queries took 77 seconds — over 100 times as long (these times do include the searches for the latest versions on the manufacturers' websites).

Still, slow may be better than nothing.

Use Win32Product with the program name that is returned by WMI.
Replace any version included in the name by a percent sign (a "wildcard" in WMI Query language).
If there is any doubt that the query will return the proper version, add TryInstallLocation, this will act as a failover: if no version is returned, UpdateCheck.hta will check if the install location is returned, and if so, use this to do a file version check on the executable.
You may also use UseProductVersion if TryInstallLocation is used.

I use a script like this to list all program names and versions found in WMI:

	Dim colInstances, i, objInstance, objSortedList, objWMIService

	Set objSortedList = CreateObject( "System.Collections.Sortedlist" )
	Set objWMIService = GetObject( "winmgmts://./root/CIMV2" )
	Set colInstances  = objWMIService.ExecQuery( "SELECT * FROM Win32_Product" )

	For Each objInstance In colInstances
		objSortedList.Item( objInstance.Caption ) = objInstance.Version
	Next

	For i = 0 To objSortedList.Count - 1
		WScript.Echo Pad( 80, objSortedList.GetKey(i) ) _
		           & vbTab _
		           & objSortedList.Item( objSortedList.GetKey(i) )
	Next

	Set colInstances  = Nothing
	Set objWMIService = Nothing
	Set objSortedList = Nothing


	Function Pad( num, str )
		Pad = Left( str & Space( num ), num )
	End Function

Check Latest Versions

To check the latest version of a program, search a web page on the manufacturer's site that shows the latest version in text (not an image).
Place its URL in WebsiteVersion.
Create a regular expression to extract the first occurrence of the version number, and place it in Regexpattern.

The download URL may differ from the URL used to check for the latest version, hence the mandatory WebsiteDownload parameter.

Manufacturers' website tend to change often, so the regular expression may at some time in the near future fail to find the version.
In that case, the latest version field in the UpdateCheck window will display the text "Not found", and a download button with caption "Check" is placed next to it.
You can either wait for the next INI file update (downloaded using the "Update Program List" button) or try and edit the Regexpattern and/or WebsiteVersion parameters yourself.

Note: Whenever you edit the INI yourself, add the CustomEntry parameter, to prevent your modifications from being overwritten at the next INI update.

Limitations

There are several issues that may prevent a correct version test result:

  1. The manufacturer's website may not contain a "hard coded" version for the program (e.g. Adobe Reader); in these cases, try WGetUseIE
  2. The manufacturer may mix different numbering systems (product version advertised on the web uses the year it was released, whereas the files use a "proper" versioning system, e.g. FileLocator Lite); I don't have a solution for these cases yet
  3. The manufacturer's website may obscure the version by using an image instead of text (e.g. VbsEdit); for VbsEdit I fixed this by keeping track of its version in a text file on my own site
  4. The manufacturer may redesign the web page (e.g. with each update)

Using the CommandLine parameter you may use any script to find the installed version.
Finding the latest version, however, always requires a "cooperative" website.


page last modified: 2015-01-15; loaded in 0.0087 seconds