Application translocation

Hi everybody!
A made an application for macOS, Linux and windows that are distributed by Bank to customers over zip. This is a logging utility for troubleshooting. Zip file is downdloaded over web. In fact, it is one-time launched app. This applications share some resources in a separate files, which are in a root folder of zip. When macOS application is launching, it relocates to some var directory, and application cant find necessary resources. Running xattr -cr is not a way, because typical users are 50+ yo. So i need a way to find the original path of app or relocate all folder or automatically clear these security flags. Or, may be, a right apple way. I believe, that making an installer for one-time lauched app is too much.
Thanks for help.

Answered by DTS Engineer in 911054022

To start, you can find a bunch of backstory in App Translocation Notes.

On Apple platforms, we use the term app to refer to a GUI program that a user launches by double clicking in the Finder (or tapping on the Home Screen, or whatever). Apps are structured as a bundle, that is, a directory ending in .app with a very specific internal structure. You can learn more about that structure in Placing content in a bundle.

If an app needs to access internal resources, it does so using the NSBundle API (Bundle in Swift). For example, if your code wants to reference an image called my-image.png, you’d add it to the app’s bundle like so:

% find Test852702.app 
Test852702.app
Test852702.app/Contents
Test852702.app/Contents/MacOS
Test852702.app/Contents/MacOS/Test852702
Test852702.app/Contents/Resources
Test852702.app/Contents/Resources/my-image.png
Test852702.app/Contents/Info.plist
…

and then find it with this code:

let u = Bundle.main.url(forResource: "my-image", withExtension: "png")!

where u is a file URL that points to Test852702.app/Contents/Resources/my-image.png.

This technique works regardless of where the user puts the app, including if the app has been translocated.

I recommend that you follow this well-trodden path, because there are many different subsystems within macOS that assumes that your app is structured this way. Gatekeeper path randomisation is one of them, but there are a lot more. For example, this bundle structure is required by code signing, and you really want to code sign your app (-:

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NSBundle is your friend

what do you mean? placing all files and binaries into a bundle?

Well, now that you mention it, bundles are your friends too.

Create a demo app using the Xcode app template. Archive it to disk. Make sure your app is organized like that.

To start, you can find a bunch of backstory in App Translocation Notes.

On Apple platforms, we use the term app to refer to a GUI program that a user launches by double clicking in the Finder (or tapping on the Home Screen, or whatever). Apps are structured as a bundle, that is, a directory ending in .app with a very specific internal structure. You can learn more about that structure in Placing content in a bundle.

If an app needs to access internal resources, it does so using the NSBundle API (Bundle in Swift). For example, if your code wants to reference an image called my-image.png, you’d add it to the app’s bundle like so:

% find Test852702.app 
Test852702.app
Test852702.app/Contents
Test852702.app/Contents/MacOS
Test852702.app/Contents/MacOS/Test852702
Test852702.app/Contents/Resources
Test852702.app/Contents/Resources/my-image.png
Test852702.app/Contents/Info.plist
…

and then find it with this code:

let u = Bundle.main.url(forResource: "my-image", withExtension: "png")!

where u is a file URL that points to Test852702.app/Contents/Resources/my-image.png.

This technique works regardless of where the user puts the app, including if the app has been translocated.

I recommend that you follow this well-trodden path, because there are many different subsystems within macOS that assumes that your app is structured this way. Gatekeeper path randomisation is one of them, but there are a lot more. For example, this bundle structure is required by code signing, and you really want to code sign your app (-:

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

can you explain about NSBundle?

Yes, it is a GUI app, in apllication.app/Contents/MacOS folder. I am afraid, i cant place all my resources inside this .app , because these resources are common for the same app for 2 other platforms. More than that, one of this files is an editable by user .ini file.

NSBundle is just an object that you instatiate with a URL. You can reference the "mainBundle" static object that always points to your app. There are methods that allow you to reference any resource files that are included with the app. Translocation is kind of like a mini sandbox. NSBundle provides access to any of those files within the app itself.

All resources do need to go inside the app bundle. Otherwise, you're talking about a situation where some sort of installation process is necessary. Generally speaking, there's nothing wrong with that, but it precludes allowing users to run a downloaded app from the Downloads folder.

I'm not sure what you mean about "resources are common for the same app for 2 other platforms." In this forum, "platform" usually refers to macOS vs iOS, and maybe some oddball tvOS, watchOS, etc. There's no problem including any kind of "foreign" resources inside an app bundle. The data may be duplicated and the zip files may be larger, but that's life.

A user editable .ini file is really not a good idea. It would be better to describe what you're trying to accomplish with this .ini file. There are probably other ways to achieve the same end result - maybe user defaults, maybe an onboarding UI, maybe a network request.