Posted on 11-04-2021 11:15 AM
I have a room of M1 Mac Minis used for a Digital Art/Printing lab. The instructors like to use a plug-in that has not yet been updated to run natively on Apple silicon, so to use the plugin the students/users have been finding the Adobe Photoshop.app, getting info, and ticking the Rosetta box manually... nearly every time they go to run the app (the user account is removed upon log out and refreshed via script).
I'm curious if anyone has any experience managing these settings. They appear to be set in a plist file in the user's Library folder: ~/Library/Preferences/com.apple.LaunchServices/com.apple.LaunchServices.plist; but I have not had any success trying to manage this with a custom config profile in Jamf, nor does dropping the preconfigured file into place during account creation keep that box checked.
Posted on 03-21-2022 05:51 AM
Hi all,
i've the same problem, i need to open with rosetta word for a plugin, but i didn't find any solution.
I've tried to put .plist file in the right directory and also package word.app with setted the flag but doesn't worked
There is someone that solved this problem?
Thanks
Claudio
Posted on 05-03-2022 12:50 AM
anyone solved?
Posted on 12-20-2022 01:25 PM
Just got done working through this so I'll post in case anyone finds it helpful.
I stumbled across this: https://gist.github.com/WardsParadox/d6a8fbe0c0d1f100b5574188e4bd627d
(Script called run_under_rosetta.py)
First off, you will need to push a Python 3 interpreter to run this script on an endpoint: https://github.com/macadmins/python
I copied the contents of run_under_rosetta.py into a new script in Jamf.
I added the appropriate shebang so the above Python interpreter would see it.
For some reason it was erroring until I added a colon on line 120 after (app_path)
I then added the path to Photoshop 2021. I usually drag an app to terminal and copy the path there. But this script didn't like the slashes that terminal was adding, so I had to remove them.
So this is the working script:
#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3
import os
import subprocess
import sys
from Foundation import * # pylint: disable=E0611 #
import objc
from SystemConfiguration import SCDynamicStoreCopyConsoleUser
def is_arm64():
"""
Determine if a Mac can run ARM64 code, whether or not the binary is running in Rosetta 2 via pyobjc
https://gist.github.com/pudquick/ca7fa134895f30b070212ea505cab5eb
Returns:
boolean: True = arm64 device (aka Apple Silicon), False = x86_64 (Intel Silicon)
"""
CF = NSBundle.bundleWithPath_("/System/Library/Frameworks/CoreFoundation.framework")
f = [("CFBundleIsArchitectureLoadable", b"BQ")]
objc.loadBundleFunctions(CF, globals(), f)
NSBundleExecutableArchitectureARM64 = 0x0100000C
return CFBundleIsArchitectureLoadable(NSBundleExecutableArchitectureARM64)
# Shamelessly Stolen from FoundationPlist (L26-106): https://github.com/munki/munki/blob/main/code/client/munkilib/FoundationPlist.py
class NSPropertyListSerializationException(BaseException):
"""Read/parse error for plists"""
pass
class NSPropertyListWriteException(BaseException):
"""Write error for plists"""
pass
def readPlist(filepath):
"""
Read a .plist file from filepath. Return the unpacked root object
(which is usually a dictionary).
"""
plistData = NSData.dataWithContentsOfFile_(filepath)
(
dataObject,
dummy_plistFormat,
error,
) = NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_(
plistData, NSPropertyListMutableContainers, None, None
)
if dataObject is None:
if error:
error = error.encode("ascii", "ignore")
else:
error = "Unknown error"
errmsg = "%s in file %s" % (error, filepath)
raise NSPropertyListSerializationException(errmsg)
else:
return dataObject
def readPlistFromString(data):
"""Read a plist data from a (byte)string. Return the root object."""
plistData = NSData.dataWithBytes_length_(data, len(data))
if not plistData:
raise NSPropertyListSerializationException("Could not convert string to NSData")
(
dataObject,
dummy_plistFormat,
error,
) = NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_(
plistData, NSPropertyListMutableContainers, None, None
)
if dataObject is None:
if error:
error = error.encode("ascii", "ignore")
else:
error = "Unknown error"
raise NSPropertyListSerializationException(error)
else:
return dataObject
def writePlist(dataObject, filepath):
"""
Write 'rootObject' as a plist to filepath.
"""
(
plistData,
error,
) = NSPropertyListSerialization.dataFromPropertyList_format_errorDescription_(
dataObject, NSPropertyListXMLFormat_v1_0, None
)
if plistData is None:
if error:
error = error.encode("ascii", "ignore")
else:
error = "Unknown error"
raise NSPropertyListSerializationException(error)
else:
if plistData.writeToFile_atomically_(filepath, True):
return
else:
raise NSPropertyListWriteException(
"Failed to write plist data to %s" % filepath
)
def main():
"""Main, duh, whatelse but RUNNNN!"""
if not is_arm64():
print("Intel device detected...no problemo!")
sys.exit(0)
# Dont' rely on python knowing which user is active as we run this run sudo via jamf
name, uid, gid = SCDynamicStoreCopyConsoleUser(None, None, None)
ls_path = f"/Users/{name}/Library/Preferences/com.apple.LaunchServices/com.apple.LaunchServices.plist"
ls_mode = "x86_64"
app_path = "/Applications/Adobe Photoshop 2021/Adobe Photoshop 2021.app"
if not os.path.exists(app_path):
print(f"Bad App Path given!")
sys.exit(1)
bundle_identifier = NSBundle.bundleWithPath_(app_path).bundleIdentifier()
file_path = NSURL.fileURLWithPath_(app_path)
bookmark = file_path.bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_(
NSURLBookmarkCreationSuitableForBookmarkFile, None, None, None
)
data = NSData.alloc().initWithBytes_length_(bookmark[0], len(bookmark[0]))
if os.path.exists(ls_path):
ls_data = readPlist(ls_path)
else:
dummy = plistlib.dumps({"Architectures for arm64": {}})
ls_data = readPlistFromString(dummy)
if bundle_identifier in ls_data["Architectures for arm64"]:
if ls_mode in ls_data["Architectures for arm64"][bundle_identifier]:
print(f"App bundle {bundle_identifier} already set to {ls_mode}")
sys.exit(0)
else:
print(f"Setting App bundle {bundle_identifier} to {ls_mode}")
else:
print(
f"App bundle {bundle_identifier} not found. Creating and Setting to {ls_mode}"
)
ls_data["Architectures for arm64"][bundle_identifier] = [data, ls_mode]
writePlist(ls_data, ls_path)
# Kill LaunchServices daemon to load saved data
subprocess.check_call(["/usr/bin/killall", "lsd"])
if __name__ == "__main__":
main()
In my use-case, a companies (GMetrix) photoshop plug-in wouldn't work without Photoshop running under Rosetta. It's a shared lab, and I didn't want every student having to check the 'Open using Rosetta' box.
I have the GMetrix install.pkg policy running a recon after if finishes. I also have a smart group called 'Has GMetrix installed'. I have the above script/policy run on a Login hook, targeting the 'GMetrix installed' smart group. So anyone with that app (well, it shows as an installed .app, but it's essentially just a Photoshop plug-in) installed, this script will run when they login. There is a ~5 second delay until the Rosetta box gets checked for Photoshop, but it works. Tested with the latest version of Monterey, but it should work with Ventura I think.
Posted on 01-10-2023 05:53 PM
Update: for some reason, this only seems to work for Photoshop 2021 and not 2022. Not sure why.