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
anyone solved?
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.
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.
Update: for some reason, this only seems to work for Photoshop 2021 and not 2022. Not sure why.