0

For a Mac app, written in Cocoa/Objective-C, a common customer support problem is that they tried "uninstalling and re-installing" in hopes of getting back to a clean state. But the problem is that the new install is still reading the configuration files and database left by the previous install. Customer just hits the same issue that caused him to uninstall in the first place. Then I have to guide him through which files to delete to get back to an OK state and/or show him the proper way to reset from the UI.

While the real pain points and bugs get fixed over time, I'd like to know if it is possible to do either of the following:

  1. When MyApp.app is moved to the trash bin, is it possible for some code can run that cleans up any crud left by the app in the user's home directory? Or something in a manifest/pinfo file that can designate certain directories or files be removed?

OR

  1. When the application is started, that it can programatically detect that it has been "re-installed" such that it can do the necessary cleanup code for the new install?
selbie
  • 100,020
  • 15
  • 103
  • 173

2 Answers2

2

On app startup you could consider:

  1. The app version number
  2. The path to the app
  3. The inode of the app, i.e. the inode of the .app directory

Store old values of these in the app's prefs/application support, compare against current on launch. Based on heuristics you can decide/guess if an app has been updated (1st), moved/copied/multiple copies (2nd), deleted and re-created (3rd), or something else. It's not perfect, it is possible a re-created app has the same inode number, but its unlikely and certainly if it does change you know its a different directory.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86
0
NSString * appPath = [[NSBundle mainBundle] bundlePath];
NSDictionary * fileAttribs = [[NSFileManager defaultManager]  
    attributesOfItemAtPath:appPath error:nil
];
NSDate * creationDate = [fileAttribs objectForKey:NSFileModificationDate];

NSDate * savedDate = [[NSUserDefaults standardUserDefaults] 
    objectForKey:@"AppBundleFileModificationDate"
];

if (!savedDate) {
    // ... App never ran before ...
} else if (![creationDate isEqual:savedDate]) {
    // ... App did run before, 
    // but bundle has been re-installed or updated ...
} else {
    // ... App did run before and has not 
    // been re-installed or updated ...
}

[[NSUserDefaults standardUserDefaults]
    setObject:creationDate forKey:@"AppBundleFileModificationDate"
];

How can you distinguish a re-install from an update? Save the app version as well, if it was an update, it has changed, it not, it's a re-install of the same version.

The code will incorrectly detect a re-install if the user moves the app to a different directory and starts it from there. You can catch that case if you also store the appPath and compare that as well.

What you write to NSUserDefaults survives as long as the user doesn't deletes the preferences of the app, which never happens automatically on Mac.

Mecki
  • 125,244
  • 33
  • 244
  • 253
  • @CRD But a move would change the path, which is mentioned in my reply explicitly (not in the code, in the text below which also belongs to my reply). Creation date is not necessarily the creation date of a file on your disk, e.g. ZIP and TAR typically keep the original creation date of a file and if I uncompress a ZIP file, then delete the app from it and umcompress the same ZIP file again (which would be such a re-install case), it would go unnoticed if I used creation date. – Mecki Dec 09 '15 at 15:33
  • @CRD E.g. you cannot get an inode number using a high level API like NSFileManager, not all file systems have real inode numbers, in which case the system will fake some (think of a FAT32 USB stick, think of network file systems like WebDAV), and inodes are not guaranteed to be stable (faked inodes are rarely stable and other than that, it's up to the filesystem if and when an inode may change, e.g. when a file is moved or by automatic defragmentation or some COW mechanism). See also http://stackoverflow.com/q/16069898 – Mecki Dec 09 '15 at 20:58
  • @CRD Mac supports FAT32 just fine. You can access a FAT32 formatted HDs or USB stick natively and also start apps from it (I do that all the time with my USB sticks). A lot of users have a remote home (so do I at work), where they can also install apps (Mac apps run just fine also from your desktop or home dir) but the remote server may may also be a Windows file server with NTFS and SMB access. Modification date (which works with all file systems AFAIK) means date of last modification and using that to detect a modification seems the most natural to me (it is what the name implies). – Mecki Dec 09 '15 at 21:42