Extension Attribute for 32 bit macOS apps

burdett
Contributor II

Apple plans to stop support for 32-bit apps across iOS and macOS. iOS 11 will remove them this fall, macOS will continue to support them until 2019. Does anyone have Extension Attribute to find the 32-bit Mac apps? I can find these in the Mac System Report, but I'd rather come up with an JAMF PRO inventory so I can look into updating those old apps, get our users used to them, or find alternatives.

10 REPLIES 10

thoule
Valued Contributor II

You have until 2019? That's very proactive of you to get on this list now.. Here's a script that will list all apps that are only 32bit. If an app is universal, it is excluded from this list.

#!/bin/sh
#Todd H for Michael Burdett 

IFS=$'
'
allApps=$(mdfind kMDItemKind==Application)

echo "<result>"
for oneApp in ${allApps[@]}; do
    listOfBins=$(ls $oneApp/Contents/MacOS/)
    for oneBin in ${listOfBins[@]}; do
        has64=$(file $oneApp/Contents/MacOS/$oneBin|grep "_64")
        if [ -z "$has64" ]; then
            hasIt=$(file $oneApp/Contents/MacOS/$oneBin|grep 386)
            if [ ! -z "$hasIt" ]; then
                echo "found one at $oneApp/Contents/MacOS/$oneBin"
            fi
        fi
        unset hasIt
        unset has64
    done
done
echo "</result>"

c_archibald
Contributor II

How do you implement that? Smart Group, Policy, etc...? I just want a list of what Apps are 32bit only & which computers have them.

yoopersteeze
New Contributor II

@c.archibald With a custom Extension Attribute: https://docs.jamf.com/10.3.0/jamf-pro/administrator-guide/Computer_Extension_Attributes.html

tlarkin
Honored Contributor

I wrote a little script to collect all 32bit apps that are installed locally and put them to a CSV file. I have shared this on Slack and have used it myself to send Apple and other various vendors lists of 32bit apps still installed. You will have to install your entire app catalog on a Mac to get a full report, as this relies on local data off of macOS.

The script will dump a CSV file on your desktop called 32bitapps.csv. I found it personally easier to automate some software installs on my Mac client and then run this script to get a report rather than relying on Extension Attributes and recons. Your mileage may vary. There is no support or warranty given or expressed with said script. I am sharing this so the community can take the data and plead and pressure with their vendors to update their apps to 64bit. Since this will technically benefit all of us if we all pressure our vendors to update their apps for macOS 10.14.

credit goes to @eng for writing the system_profiler parser that I just borrowed from him :-)

#!/usr/bin/python

"""
this code will run through all installed apps, which are locally installed
and generate a CSV file on your desktop listing all 32bit apps
"""

import subprocess
import plistlib
import csv
from Foundation import NSHomeDirectoryForUser
from SystemConfiguration import SCDynamicStoreCopyConsoleUser


def get32bitapps():
    """function to get list of 32bit apps from System Profiler"""
    # use a list to generate a subprocess command
    cmd = ['/usr/sbin/system_profiler', '-xml', 'SPApplicationsDataType']
    # execute profiler command via subprocess
    proc = subprocess.Popen(cmd, shell=False, bufsize=-1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, err = proc.communicate()
    plist = plistlib.readPlistFromString(output)
    # create a blank list to populate app info into
    app_list = []
    items = plist[0]['_items']
    for item in items:
        # test for 32bit only apps and add them to a dictionary
        if 'no' in item.get('has64BitIntelCode'):
            app_dict = {}
            app_dict['path'] = item.get('path')
            app_dict['name'] = item.get('_name')
            app_dict['version'] = item.get('version')
            app_list.append(app_dict)
    return app_list

def write_csv(apps):
    """function to take a dictionary of 32bit apps and output to a CSV file"""
    # this code will output to a CSV file on your desktop and list 32bit apps
    currentuser, uid, gid = SCDynamicStoreCopyConsoleUser(None, None, None)
    user_home_folder = NSHomeDirectoryForUser(currentuser)
    file = user_home_folder + '/Desktop/32bitapps.csv'
    with open(file, 'wb') as csv_file:
        keys = apps[0].keys()
        dict_writer = csv.DictWriter(csv_file, keys)
        dict_writer.writeheader()
        dict_writer.writerows(apps)


# run the above functions to get desired output
applist = get32bitapps()
write_csv(applist)

donmontalvo
Esteemed Contributor III

@yoopersteeze wrote:

@c.archibald With a custom Extension Attribute: https://docs.jamf.com/10.3.0/jamf-pro/administrator-guide/Computer_Extension_Attributes.html

Not sure I'd ever want to use an EA to do this kind of thing, in this case the script took 7.758s:

# time /path/to/yourScript.sh
<result>
...[snip]...
...[snip]...
...[snip]...
</result>

real    0m7.758s
user    0m3.766s
sys 0m5.400s

We limit our EAs to scripts that take .1s or less....anything that takes more time is moved to a script that runs once per day via policy, spits out a file to /Library/COMPANYNAME/SearchResults and then an EA can pick up the content of the file. Just a thought. :)

1646737379a945cdad6f057082c6dbb3

For example a script to get the list of 32-bit apps:

#!/bin/sh

tempFile=/tmp/.32bitApps_unsorted.txt
outputFile=/Library/COMPANYNAME/SearchResults/32bitApps.txt

# Create list
/usr/sbin/system_profiler SPApplicationsDataType | grep -B 6 -A 2 "(Intel): No" | grep "Location:" | sed -e 's/^[ 	]*//' | sed -e 's/Location: //g' > $tempFile

# Sort list
/usr/bin/sort $tempFile > $outputFile

exit 0

Then an EA to scoop up the file content:

#!/bin/sh

outputFile=/Library/COMPANYNAME/SearchResults/32bitApps.txt
fileContent=$( cat $outputFile )

if [[ -e $outputFile ]]; then
    echo "<result>$fileContent</result>"
else
    echo "<result>FileDoesNotExist</result>"
fi

PS, expect the line return bug in JSS to bite ya on the EA.

--
https://donmontalvo.com

PeterG
Contributor II

<never mind> :-|

Matt_Roy93
Contributor

This is great! Thanks!

rwp16
New Contributor

Hello. This works great. Thank you! Although I am curious as to how people are filtering the results and deciding what applications to focus on. I pulled a report of all apps that the extension attribute gathered and the list has roughly 950 unique apps. Below is an example of one computers list that it returned. Any advice on how to approach these types of lists would be great. Thanks in advance. - Rusty

AAM Registration Notifier.app
AAM Updates Notifier.app
AAMLauncherUtil.app
ACR_10_0.app
Adobe Application Manager.app
Adobe Extension Manager CC.app
COCM_1_0_32.app
COPS_1_0_32.app
CORE_1_0_32.app
CORG_1_1_32.app
CitrixOnlineLauncher.app
EndNote X7.5.3 Updater.app
EndNote X7.7.1 Updater.app
EndNote X7.8 Updater.app
EndNote X7.app
EndNote X9.app
ExtendScript Toolkit.app
Fetch.app
GoToMyPC.app
ILST_22_0_1.app
InkServer.app
Install.app
InstallBoxTools.app
KeyCheckout.app
KeyMap.app
Logitech Camera Settings.app
PHSP_19_0_1.app
SLLauncher.app
Setup.app
Template.app
Uninstall Product.app
Uninstaller.app
adobe_licutil.app
naib.app
quicklookd32.app
tn3270 X.app
zoom.us.app
{135274B3-69EE-4AE8-ACCE-1718A1EBC8CC}.app
{244FD30F-63F1-49B9-9D98-1150FF4FFCB1}.app
{BFFCB3A0-F126-4A97-ACEB-3C74B50AC04E}.app

tlarkin
Honored Contributor

every line of output in an EA is a row in the database, I would not recommend you using EAs for this. EAs were not really designed for this purpose. I would recommend installing your entire app catalog on a system and running a local report to accomplish this

luispalumbo
Contributor

Hi all,
I've just found this post on StackExchange, https://apple.stackexchange.com/questions/314460/how-to-identify-32bit-applications-on-macos-without..., where a user mentioned that using the "mdfind" command, which is used by Spotlight, it speeds up the search.
This is based on @thoule script, but simpler and I think @donmontalvo will enjoy it.
I tried this one:

mdfind "kMDItemExecutableArchitectures == '*i386*' && kMDItemExecutableArchitectures != '*x86*'"