Application Support folder at runtime

I'm trying to store the user's license key in a folder within Application Support as suggested by Apple docs.


The Finder shows a path of Macintosh HD | Library | Application Support which contains a number of folders for apps ranging from Google to VMWare just as I would expect. If I try to create a new folder there, the Finder causes a "Finder wants to make changes" dialog to appear.


When my app runs, it tries to create a folder (based on its bundle ID per the documentation) called...


/Library/Application Support/com.bookup.chessopeningswizardprofessional/


The attempt to create the folder fails.


So the app then asks for the user's application folder and tries to create a folder called...


/Users/michael/Library/Application Support/com.bookup.chessopeningswizardprofessional/


This attempt succeeds according to the function result - but the folder is not actually created. The folder neither appears in the Finder nor is it accessible by the app when it attempts to store a file in that folder.


What would cause the Foundation call to confirm the creation of the folder and yet not have the folder exist?


And if that connot be resolved, what other ways can/should I save the user's license key other than the approach recommended in Apple's docs?

Accepted Reply

The user-level Library folder is where this should go.


Is your application sandboxed? If so, then the "Application Support" folder is actually a folder of a different name inside your app container, and the Finder may not show such folders to users by default.


Regardless of what the Finder tells you, can you create and then read a file in the folder? If so, then I don't think there's any problem with your app.

Replies

You have no permission to write to this Library folder:


Look here for details:

h ttps://support.apple.com/en-us/HT204899

The user-level Library folder is where this should go.


Is your application sandboxed? If so, then the "Application Support" folder is actually a folder of a different name inside your app container, and the Finder may not show such folders to users by default.


Regardless of what the Finder tells you, can you create and then read a file in the folder? If so, then I don't think there's any problem with your app.

I'd recommend serializing license keys to NSUserDefaults and reading it from there over "move a license file into ~/Library/Application Support/bundleid/". I've used the license file approach for years and I will never opt for it again:

  • Files can fail in many ways. Broken permissions, read-only folders, full disk, case-sensitive file systems, weird administrative setups (tools that clear/reset certain directories on logout). I've encountered all of these except for the full disk. When it fails, walking a user through the steps to "fix it" is a tedious exercise, especially when ~/Library is hidden by default on modern macOS releases*. It's even more fun if you're doing customer service for older versions which don't present the error to the user. Always present errors (and always from the main thread).
  • Distributing license files is annoying. Building a tool to email a customer his license file? Your server code now has to deal with attachments -- which is easy enough with 3rd party libraries and tools but one more annoyance. Then you'll encounter customer spam filters which set higher spam scores for messages with attachments. You could store the license file server-side and link it as a download, but that leaves a user without anything useful when searching their email in offline scenarios (and you'll probably want to have license links expire for security purposes, anyway). More work from both ends.
  • License files require more app integration on your end. You probably want to create an NSDocument with a custom file extension so a user can double-click your license file to activate it. It would also be nice to have a file icon for that document. Maybe include a Quicklook preview that shows the licensee name and a higher quality image. More work for you. Even then, you're not bulletproof: the file registration database can get messed up and then your license file doesn't open in your app with a 2x click. "Drag and drop your license file onto the app icon" should always work, but isn't as nice. There are other cool things but they take more work**.
  • Downloading license files is annoying. If you have to support back to 10.6, you can encounter older Safari releases which need extra help on the server side or else your file extension might change upon download. More work.
  • Every customer I've interacted with, pre-sales and immediate post-sale, when asking about licensing / "where's my license" has mentioned a "code" -- never a file. License codes / copy-pasta strings match user expectations / mental models, not license files. All the big boys use codes, the App Store has promo "codes", etc. License files are fighting the trend. From the user end, working with a file is more work than a copy/pasta.


Compare this to saving into NSUserDefaults:

  • Save/read your license key as a string, or as data with NSKeyedArchiver/NSKeyedUnarchiver. Validate it. Done.
  • No errors to present or worry about. Apple takes care of it for you. I've yet to have NSUserDefaults fail me. If it does (i.e., a user reports preferences are "not saving", etc.), that's indicative of a deeper problem out of your domain that would affect multiple apps, so you don't get singled out for a bad user experience.
  • Want to include an "Unlicense" feature? Just remove the key from NSUserDefaults. If you were to use license files, your unlicense step subjects you to every way file interaction can fail.


There are some other things, but that's the gist of it.


Are there any particular reasons for storing a license file in ~/Library/Application Support/bundleid/, or any license file advantages I'm missing?



* You can tell them to hold Option while choosing Go from the Finder to make Library appear, but it's one more step.

** I've seen some apps keep a running NSMetadataQuery and auto-license once it detects a license file (which is super cool), but I never worked out how to handle duplicates and some other edge cases. Still more work for you.

The app is not sandboxed. It is delivered outside the app store.


You are correct that there was no problem with my app. The problem was that I didn't know the User's folder was hidden. The app reported success at creating a sub folder there but I could not see it. Revealing that folder in the Finder showed me the typo in the file name used by my app.

When I say license file, I mean the file that contains the license key. I, like you, do not care for license files as you describe them.


I am using Delphi so I have no access to NSUserDefaults like one does in XCode.


What broke it open for me was your footnote explaining the use of the Option key in the Go menu of the Finder. I had no idea that folder was hidden. Revealing that folder in the Finder showed me the typo in the file name used by my app.