It’s sometimes unclear to developers that appdata–what’s stored in %localappdata%packages<your package> in folders like LocalState, RoamingState, and TempState–is not dependent on the version of the app that’s using it. By design, app data is maintained across app updates. That is, the act of installing an app update has no effect whatsoever on app data, except when an app has a background task registered for the ServicingComplete trigger and that background task makes changes.

The version of the app and the version of the app data are two separate things: you can have many revs of the app using the same app data structures, so there’s nothing you need to do when upgrading/updating the app. It’s only when you want to change the app data that you then need to version the app data specifically. Here’s what to do:

  1. Even in your first app version, you should be calling Windows.Storage.ApplicationData.SetVersionAsync to assign a version number to your app data as a whole. This becomes important for how the roaming cloud service manages and maintains copies of the app data when a user hasn’t updated every app on every device.
  2. When you’re going to change the appdata version, the second parameter to SetVersionAsync is a function that will be called to migrate from one version to another. This is the trigger to go through an older version of app data (as it might be on disk) and refresh/update the structures. Windows will assume the migration is complete when you return from this. (See scenario 9 of the Application data sample.)
  3. You can call SetVersionAsync in a ServicingComplete background task, but be mindful of the CPU quotas on background tasks if you have a lot of work to do.
  4. You can always maintain per-file or per-settings versioning on your own, without ever changing the overall version number. The danger of this with roaming state, however, is that Windows will assume that all files are the same version, and because the last writer wins, it’s possible that an earlier version of the app on one of the user’s devices will overwrite a newer version of a file on some other device. I think it’s best to avoid adding another layer of complexity to this scene.

In short, apart from a background task, the callback you provide to SetVersionAsync is where you make any updates/changes to app data, and this would typically happen when you launch an app update that knows it’s going to use a new version of state. Before that time, the app data will be the same as before the app was updated.

 

BONUS: a related question to all this is what happens if an app is suspended and terminated, and then updated? Does that terminated state carry through to the next launch? Well, in Windows 8 the previousExecutionState flag gets reset when an update happens; in Windows 8.1, however, it’s preserved, so it is possible for a freshly updated app to be asked to reload session state from a previous version. If this is a problem for your app, either change the state version for the update, or simply check for a flag in your sessionState to determine whether it came from your updated app or a previous version. The latter is a more lightweight solution and won’t affect roaming state versions in the cloud. It’s one good place where even having a distinct version mark in your sessionState can be helpful, as sessionState is never roamed anyway.

 


Comments are closed