Posted on 03-17-2016 01:08 PM
I am working on updating the EA, and stuck on format of evaluating an expression.
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!
Posted on 03-17-2016 01:24 PM
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>;"
Posted on 03-17-2016 01:28 PM
@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!
Posted on 03-17-2016 01:35 PM
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
Posted on 03-17-2016 01:37 PM
@CAJensen01 Thank you sir!
Posted on 03-17-2016 01:40 PM
@thoule Thank you very much!
Posted on 03-17-2016 01:40 PM
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)
Posted on 03-17-2016 01:46 PM
@stevewood For some reason it does not work for me with Office 2016. AE shows no value
Posted on 03-17-2016 01:54 PM
@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.
Posted on 03-17-2016 02:01 PM
@elliotjordan I also thought about using smart groups, but still prefer dealing with one EA instead of four smart groups
Posted on 03-17-2016 02:14 PM
@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...
Posted on 03-17-2016 03:19 PM
@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
Posted on 03-17-2016 03:29 PM
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.
Posted on 03-17-2016 07:21 PM
@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.
Posted on 03-18-2016 06:04 AM
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.
Posted on 03-18-2016 08:07 AM
@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.
Posted on 03-18-2016 08:41 AM
@thoule Thank you sir!