Cocoa/Mac - external config settings for running app - cocoa

On windows, we use registry or .ini or xml config etc for settings that apps can pull in at run time w/o making code changes.
On Mac/Cocoa, what're the best approaches to do that and what are the corresponding APIs?

See NSUserDefaults and the User Defaults Programming Topics. NSUserDefaults stores the data as a property list in the ~/Library/Preferences directory.

As #ughoavgfhw answered, per-user preferences should be stored in ~/Library/Preferences, and NSUserDefaults is available to support that.
If you are instead thinking of configuration information (the line between configuration and preferences being of course fuzzy) then you might wish to use the Application Support folder. There are two of these, per-user located at ~/Library/Application Support and system-wide at /Library/Application Support. In either of these create a folder named after your application or company and stored whatever you wish to in it. If you are planning on submitting to the Mac App Store only the per-user folder is allowed - you must replicate your configuration information for every user.

Related

Deploy multiple apps with "shared private" Qt frameworks on OS X

I have a set of applications that work together. It should be possible to start each of these applications individually by the user (i.e. one application provides a monitoring feature, another a configuration feature etc), therefore I would like them to show up in the Applications folder as different applications (possibly within a directory).
The applications are based on Qt5, so I would like to package Qt along with the applications privately to ensure that Qt is present and available. On the other hand I would like to make sure that I only include a single copy of Qt to avoid bloating the system.
I am using a package installer, due to the inclusion of a LaunchDaemon as well.
How do I place the Qt frameworks needed in order to avoid having multiple copies?
Here's the naive way:
/Applications/
MyCompany/
Foo.app/
Contents/
Info.plist (must use its own plist to specify some properties)
MacOS/
foo
Frameworks/
Qt-Goes-Here??
Bar.app/
Contents/
Info.plist
MacOS/
bar
Frameworks/
Qt-Goes-Here?? - Or can this be a link to the other location?
Since I am not a Mac-guru, any input (including informing me that I am trying something stupid) is very welcome!
There are two possibilities here, the first is
/Library
and the second
/Library/Application Support
If you look there, you'll find folders with contents for various applications. You should be able to create a folder there and add the Qt Framework, then update your applications to point to that using install_name_tool
The docs state the following for /Library: -
The Library directory is the top-level directory for storing private
app-related data and preferences. There are several Library
directories scattered throughout the system but you should always use
the one located inside the current home directory. Do not store files
directly at the top-level of the Library directory. Instead, store
them in one of the specific subdirectories described in this table. In
OS X v10.7 and later, the Finder hides the Library directory in the
user’s home folder by default. Therefore, you should never store files
in this directory that you want the user to access. To get the path to
this directory use the NSLibraryDirectory search path key with the
NSUserDomainMask domain.
For /Library/Application Support: -
The Application Support directory is where your app stores any type of
file that supports the app but is not required for the app to run,
such as document templates or configuration files. The files should be
app-specific but should never store user data. This directory is
located inside the Library directory. Never store files at the top
level of this directory: Always put them in a subdirectory named for
your app or company. If the resources apply to all users on the
system, such as document templates, place them in /Library/Application
Support. To get the path to this directory use the
NSApplicationSupportDirectory search path key with the
NSLocalDomainMask domain. If the resources are user-specific, such as
workspace configuration files, place them in the current user’s
~/Library/Application Support directory. To get the path to this
directory use the NSApplicationSupportDirectory search path key with
the NSUserDomainMask domain.
The full documentation can be found here.

How to make MSI file by vs2010 that allow my app to create .txt file in Client Machine which is installed in C:\Program File\myAppFolder

I'm deploying a .NET application with VS2010. My application creates .txt file in the logs folder in the same directory with .exe:
app.exe
add.exe.config
logs (folder)
I used setup project to create a MSI installer. When I installed in the client machine C: drive or any drives I have no problem to create the .txt file, but when I installed in C:\Program File\myAppFolder or C:\Program File(x86)\myAppFolder I cannot to create the .txt file.
It is a poor design to write to install location for your application. It is better to write to the ApplicationDataFolder. The ApplicationDataFolder is under the user profile and the application will have access to write there when run as that user. #Ken White provided a very good pointer to an existing StackOverflow answer about this.
If this is a legacy application that must write to that folder, then you'll need to modify the permissions on the log folder such that all users can write to the folder. This is possible to do with the Windows Installer (aka: MSI) but I'm not sure that the Visual Studio setup projects expose it. The WiX toolset definitely supports doing such things.
An old post but I needed to do similar recently so I guess it is still valid! While I don't advocate bad design, in the real world sometimes we have to bend to requirement.
Writing to the application folder is possibly under Win7 and it is possible to set this up via an installer class in an MSI created by VS2010. You just need to give a relevant group (suggest either the "Users" group, or if you want to give more control over who gets what, supply a selection screen) Write-Data access.
Using DirectoryInfo on a path you can then get the security data from GetAccessControl.
When you have your Group known, get the SID for the group and AddAccessRule also supplying the required ControlType value.
Then set the access control on the DirectoryInfo object (SetAccessControl) using the security data object.
You can get the SID from the Groups principal object if you do a search with PrincipalSearcher.
Hope this helps
paul
This generally all depends on:
Whether your app requires to be run as administrator for other reasons and..
Whether your app is provided for limited users.
If the app requires elevation for a bunch of other reasons (and not just updating files in restricted locations) then the normal way is to have an elevation manifest embedded in your app. This isn't a good thing from the security point of view, but if you absolutely need admin privilege then this is the way to do it.
If the only operation requiring elevation is updating/creating data in the Program Files folder then don't put the file there. Every case of this that I've seen has been lazy programming where the code just refers to the file name and consequently it goes in the Program Files folder (more accurately in the same folder that the app runs in). The cure for this is to put the data file in the correct location (such as User's Application Data folder). As Rob Mensching says, you should alter the permissions on the install folder only if this is a legacy app that you cannot change.

Application permission issues on OS X, when distributing application

we are making an Application for OS X, however, when the .app is copied on another MAC, we have problems with reading and writing files
on one MAC, everything works great from the start...
the other one will not write certain files and another 2mac will not write certain different files
if i go to show application contents and wants to edit the file by myself, i get a writing permission denied
how to distribute an MAC application so there are no such issues? so all files can be read and write by the current user
does there have to be some authorization or code sign, or smth. different in this form, in addition to normal code?
thank you
It sounds like your application tries to write files within its own application bundle. The correct solution here is: DON'T DO THAT! The only time your application bundle should be written to is when it's installed or updated.
Files that the application needs to write to should be stored in the user's home folder, generally under ~/Library. See this note in Apple's dev docs.
Preference and settings files in ~/Library/Preferences/<appbundleid>.plist; use NSUserDefaults.
Data the app manages for the user in ~/Library/Application Support/<appname> (the docs say to use the bundleid, but everyone -- Apple included -- uses the app name instead).
Cache files in ~/Library/Caches/<appbundleid>.
Temp files, use NSTemporaryDirectory
If you need to share settings & files between users, that should generally go in /Library/Application Support/<appname>, except that you really shouldn't be doing that at all.
In the past I've always used PackageMaker to create installers. An installation package can authenticate with root privileges so you can set permissions after the install. I don't have it in front of me right now but if you look around you should be able to see a Post-Installer script line. Write a shell script that manually sets the permissions of each file you have in question and then have the package execute that script after the install is finished.
You can find PackageMaker at /Developer/Applications/Utilities/PackageMaker

Mac OS folder locations

We have an application that we're porting to Mac OS from Windows. Once installed, the user can customize the functionality of the application by editing certain approved "data files" with a text editor. Once saved, the application can be reloaded to compile and load the contents. A core part of the program is the editing and sharing of these data files, and the program provides a friendly interface to allow the user to edit them.
On Windows, these folders are located under a standard folder, accessed through a shell constant, that our installer makes accessible to all users. Once installed, any user can run the application and edit the data files it uses.
What is the equivalent folder to use for the mac? Is there somewhere we can put stuff that is accessible to all users normally, or do we have to flag it as "all users can access" somehow?
Edit: A couple of users have suggested /Users/Shared. Aren't files in /Users/Shared still limited somehow to the user who created them? I remember trying to copy files between accounts in /Users/Shared, and I had to "take ownership" of the files in /Users/Shared before I could do anything with them.
Read this document. It has a section on where to put application files. I doubt /Users/Shared is the right directory for what you want to do; a subdirectory within /Library/Application Support/ is probably more appropriate. Remember, though, that non-admin users will not be able to write there by default. In that case, you can fall back to using the corresponding directory in the user's home folder.
Don't hardcode paths to special directories. Rather, you should use the NSFileManager methods URLsForDirectory:inDomains: or URLForDirectory:inDomain:appropriateForURL:create:error:, or the Folder Manager from Carbon if you're not using Objective-C.
/Users/Shared on a Mac is a folder available to any user. Hope this helps.
Use /Users/Shared/your_application_name .

Where you you store your setting.xml?

For several of our applications we use an application configuration file. It usually just stores some directory paths and a few universal settings. We usually save it in the application directory (C:/Program Files/MyAppName)
One problem we see is users want to edit this (from the application) while logged in as a user that doesn't have access to write to the directory. Our applications are commonly installed and initially configured as an admin, but mostly used by (several different) limited users.
Is there a good way to make the setting.xml file read/write accessible to all users? Or a good place to put it?
C:\Documents and Settings\All Users\Application Data\<Your App> might be a decent place to consider.
Pass CSIDL_COMMON_APPDATA to SHGetSpecialFolderPath to get the writable, shared root data directory. Given that you can create a directory for your company and application.
Application data folder or moving to registry.
How important is localization? If localization isn't a high priority, you can store the files in %allusersprofile%\Application Data\ - that's the appdata folder accessible to all user accounts, and will work regardless of where things are installed, but only on English operating system installs.
If you want to store a file in the local user's directory and give each user their own, you can use %appdata% - that one will be entirely localized. But, each user will need their own copy, so it won't work if you need a common configuration.
If you need it to both be common to all users, and be 100% localized, you need to do a bit more work. I tried to find something like %allusersappdata%, and while I can find references online to that string, I can't get it to work on my own system. The workaround I found was to pull up %appdata% to find the localized text for the words Application Data, then use that to browse to that subfolder under %allusersprofile% - a bit more complicated, but it's the most bulletproof way I can find to do it. Someone please correct me if there's a direct path you can use to get to that folder.
I would try this previous question.
Which says:
System.Environment.SpecialFolder.LocalApplicationData
If you are using .NET

Resources