Skip to main content

I am working on updating the EA, and stuck on format of evaluating an expression.





CURRENT_EXCEL_VERSION="15.20"



if [ -d /Applications/Microsoft Excel.app ]



then



EXCEL_VERSION=$( sudo defaults read /Applications/Microsoft Excel.app/Contents/Info.plist CFBundleShortVersionString )



else



echo "<result>OfficeNotInstalled</result>"



fi



if [ $EXCEL_VERSION -lt $CURRENT_EXCEL_VERSION ]



then



echo "<result>True</result>"



else



echo "<result>False</result>"



fi




The first "if" works as well, 2nd "if" returns "False" all the time. I understand that it is because of non-number, string value like "15.19.1" vs "15.20", but do not know how to the evaluating an expression should be changed.



Would you please help?



Thanks!

Here's what I'm doing for a Microsoft Office EA, to make it an integer for easier scoping. Ultimately, it makes the number five digits. 15.18.0 would convert to 15180, and 15.19.1 becomes 15191. A smart group can then be set to update to 15.19.1 if the value is greater than 0 (meaning installed) and less than 15190



#!/bin/sh

if [ -x "/Applications/Microsoft Outlook.app" ]; then
IFS='.'
## Here we read in the current version number, and put it into an array.
VERSIONNATIVE=`defaults read "/Applications/Microsoft Outlook.app/Contents/Info.plist" CFBundleShortVersionString`;
arrVERSIONNATIVE=($VERSIONNATIVE)
## Here we remove the periods and spaces in the version number.
VERSION=`echo $VERSIONNATIVE | sed 's/[.]//g' | sed 's/ //g'`
var0='0';
## Counting gets the number of total digits
COUNT=`echo ${#VERSION}`;
COUNTsubV=`echo ${#arrVERSIONNATIVE[0]}`;

## Check to see if there is a build number, if not, add zero digit. Eg 15.19 becomes 15190.
if [ -z "${arrVERSIONNATIVE[2]}" ]; then
arrVERSIONNATIVE[2]="$var0"
echo "No build number, so appending a zero on the end of the number, to: " $VERSION
fi
## Next, we need to see how many digits the secondary version number has, and ensure it ultimately has two.
if [ $COUNTsubV -lt 2 ]; then
arrVERSIONNATIVE[1]="$VERSION$var0";
COUNT=`echo ${#VERSION}`
fi

VERSION=""${arrVERSIONNATIVE[0]}""${arrVERSIONNATIVE[1]}""${arrVERSIONNATIVE[2]}""
else
VERSION="Not installed";
fi
echo "<result>$VERSION</result>;"

@CAJensen01 ... you are my hero. The "fake integer" version strings have been the bane of my existence since we set up Casper, I think I'm going to have to steal that approach. It will make like SOOOOO much easier for package management for us!


Here's my section of code that does versioning... Part of a much larger piece of code.



#!/bin/sh

vercomp () {
# echo "Starting: $1 $2"
if [[ $1 == $2 ]]
then
return 0
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]})); then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}

latestVersion="13.4.5"
appPath="/Applications/TextEdit.app"

installedVersion=`defaults read "$appPath/Contents/Info.plist" CFBundleShortVersionString'`

vercomp $latestVersion $installedVersion
newerApp=$?
if [ $newerApp == 1 ]; then
# An update is available. Record it for the GUI
echo "update for $appPath is available"
elif [ $newerApp == 2 ]; then
echo "User has a newer version of $appName than on the server. Do Nothing"
elif [ $newerApp == 0 ]; then
echo "User has same version of $appName as is installed. Do Nothing."
else
echo "Unknown Error occurred comparing version on $appName. You have $installedVersion and the latest is $latestVersion."
fi

@CAJensen01 Thank you sir!


@thoule Thank you very much!


And just because, this is a Python script EA that is part of the AutoPKGr process for updating Office apps. This is set for 2011, but could easily be updated for 2016. I'm not sure if this is the work of @elliotjordan or not:



#!/usr/bin/python
'''Office version extension attribute.

Checks the lowest version number for the main apps if found.
Reports OfficeNotInstalled if something is missing.
Reports True if Office is in need of and capable of updating (min version met)
Reports False otherwise

Note: This a pretty minimal check for version and existence!

'''

from distutils.version import StrictVersion
import subprocess
import os.path
import shlex
import sys

PREFIX = '/Applications/Microsoft Office 2011/'
FILES_TO_CHECK = {'Microsoft Excel.app/Contents/Info.plist',
'Microsoft Word.app/Contents/Info.plist',
'Microsoft Powerpoint.app/Contents/Info.plist',
'Microsoft Outlook.app/Contents/Info.plist'}
CURRENT_VERSION = StrictVersion('14.6.2')
MINIMUM_VERSION = StrictVersion('14.1.0')

results = []

for file in FILES_TO_CHECK:
args = shlex.split('defaults read "%s" CFBundleShortVersionString'
% os.path.join(PREFIX, file))
process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

output = process.communicate()
if output[1]:
result = 'OfficeNotInstalled'
print '<result>%s</result>' % str(result)
sys.exit()
else:
results.append(StrictVersion(output[0]))

results.sort()
result = results[0]

# 14.1.0 is required for upgrade packages
if result < CURRENT_VERSION and result >= MINIMUM_VERSION:
result = True
else:
result = False

print '<result>%s</result>' % str(result)

@stevewood For some reason it does not work for me with Office 2016. AE shows no value


@stevewood I think that's Shea Craig's extension attribute, originally created here. It's part of the jss-recipes repository, not actually part of AutoPkgr itself.



@mhasman The EA Steve posted is specific to Office 2011. No such EA is necessary for 2016 because the apps are now standalone, and trying to version them as a unit would serve no purpose. I use smart groups, examples of which can be found here: Word, Excel, PowerPoint, Outlook.


@elliotjordan I also thought about using smart groups, but still prefer dealing with one EA instead of four smart groups


@thoule Todd, question for you, please
Any chance I may call for vercomp () from if [] ? What would be the format, please? Like that:



if [ $(vercomp $latestVersion $installedVersion) == 1 ] then...


@CAJensen01 Careful with that method.



Eg. which is greater



15.2.10 or 15.18.0



Check out my pre-flight offering on Adobe Versions
The getVersion checkVersion combo will compare each part of the version


Python's LooseVersion class is a less painful way to compare versions, if you must use a script.



But the real solution is for Casper to intelligently compare versions itself. Take a moment to voice your opinion in this feature request, if you haven't already.


@sean , Not too worried about it. At this point I haven't seen MS release anything over a .1 build, and 15.2 is numbered as 15.20. But it's easily adjustable if it needs to be adjusted.


@CAJensen01



You might not be too worried, but you are posting this script as a solution to others who may not totally understand the consequences or may try and apply it to other apps where it might be an issue. So highlighting for their benefit.



But as @elliotjordan has pointed out, this really should be handled by Casper if it doesn't yet.


@mhasman
To wrap it in an if block, it'll expect 0 as success. Or in this case, an update is available. So I adjust the vercomp function to return 0 if an update is avialable, then can call the function in an if block.



vercomp () {
# echo "Starting: $1 $2"

if [[ $1 == $2 ]]
then
return 2
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros

for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros

ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]})); then
return 0
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 1
fi
done
return 2
}

update() {
appName="$1"
latestVersion="$3"
appPath="$2"
updatePolicy="$4"

installedVersion=`defaults read "$appPath/Contents/Info.plist" CFBundleShortVersionString`

if $(vercomp $latestVersion $installedVersion); then
echo "update available for $appName. $installedVersion is installed, but $latestVersion is out."
jamf policy -event $updatePolicy
else
echo "no update right now for $appName. $installedVersion is installed, but $latestVersion is out."
fi
}

update "Text Edit Pro" "/Applications/TextEdit.app" "13.4.5" "updateTextEdit"
update "Microsoft Word" "/Applications/Microsoft Word.app" "15.20.0" "updateMSWord"


EDIT: wrapped the checking into a function 'update', so you can loop through different programs. And demo how you can update using custom triggers to call a jamf policy.


@thoule Thank you sir!


Reply