18

I have been using ApplicationDeployment.CurrentDeployment.DataDirectory to store content downloaded by the client at runtime which is expected to be there every time the app launches, however now I've found this changes seemingly randomly if the application is updated.

What is the best reliable method for storing user data for the application in click-once deployments?

Currently I've been using the following method

private const string LocalPath = "data";

public string GetStoragePath() {
    string dir;
    if (ApplicationDeployment.IsNetworkDeployed) {
        ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
        dir = Path.Combine(ad.DataDirectory, LocalPath);
    } else {
        dir = LocalPath;
    }
    return CreateDirectory(dir);
}

I originally followed the article Accessing Local and Remote Data in ClickOnce Applications under the heading ClickOnce Data Directory which states this is recommended path.

NOTE: CreateDirectory(string) simply creates a directory if it doesn't already exist.

I have found the root cause of my problem is I'm creating many files and an index file, this index file contains absolute paths, click-once moves the content (or copies) on an upgrade, so the absolute paths no longer exist. I will investigate isolated storage as Damokles suggests to see if this has the same side affect for click-once deployments.

Brett Ryan
  • 26,937
  • 30
  • 128
  • 163

3 Answers3

23

Another option is to make a directory for your application in the user's AppData folder and store it there. You can get a path to that with this:

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

You'll find a lot of applications use that (and it's local equivalent). It also doesn't move around between ClickOnce versions.

Tridus
  • 5,021
  • 1
  • 19
  • 19
  • I have chosen this approach as it's the less intrusive change. Using roaming isolated storage may have been the best approach, however that will require a lot of changes all over my application, where this is a single line change. I thank you very much for this Tridus. – Brett Ryan Jul 21 '11 at 03:37
  • Here is a question for you, guys. What happens with these files when you uninstall ClickOnce application? – Alex Sorokoletov Feb 08 '15 at 20:17
  • @AlexSorokoletov Nothing. They're not part of the application so they stick around. – Tridus Feb 12 '15 at 11:08
  • @AlexSorokoletov btw it's possible to customize a ClickOnce uninstallation process and remove this data on uninstall if you wish. – kot331107 Nov 12 '17 at 21:03
  • @kot331107 would be great if you could share information about that. – Alex Sorokoletov Nov 13 '17 at 05:08
  • @AlexSorokoletov it was a long time ago but I guess I've used this article https://www.codeproject.com/Articles/506162/ClickOnce-application-autostart-and-clean-uninstal as first-steps. – kot331107 Nov 14 '17 at 14:31
5

Check out IsolatedStorage this should help. It even works in partial trust environments.

To keep you data you need to use the application scoped IsolatedStorage

using System.IO;
using System.IO.IsolatedStorage;
...

IsolatedStorageFile appScope = IsolatedStorageFile.GetUserStoreForApplication();    
using(IsolatedStorageFileStream fs = new IsolatedStorageFileStream("data.dat", FileMode.OpenOrCreate, appScope))
{
...

code taken from this post

Community
  • 1
  • 1
Leonard Brünings
  • 12,408
  • 1
  • 46
  • 66
  • Thanks Damokles, I'll look into it. I found that ClickOnce actually copies my data, but I had stored absolute paths and ofcourse the old files no longer exist, will isolated storage have the same problem or will click-once leave it alone for me? – Brett Ryan Jul 20 '11 at 11:02
  • @Brett: yes IsolatedStorage will fix that problem if you use it correctly. – Leonard Brünings Jul 20 '11 at 15:38
  • Demokles, thankyou very much for this answer, I do think this would be a great approach and will keep this in mind for new applications, however I've chosen to use the `ApplicationData` approach as it's a far less intrusive change. I thank you very much for your answer. – Brett Ryan Jul 21 '11 at 03:39
  • 1
    Probably don't want to use isolated storage if you want your data persisted with updates. ClickOnce puts isolated storage in the DataDirectory, and won't carry it forward. – RobinDotNet Aug 01 '11 at 20:09
  • 1
    @Robin read http://stackoverflow.com/questions/202013/clickonce-and-isolatedstorage if you use the correct scope you don't have trouble with new versions – Leonard Brünings Aug 02 '11 at 08:23
4

It depends on the data you are saving.

You are currently saving to the Data Directory which is fine. What you need to be aware of is that each version of the application has its own Data Directory. When you update ClickOnce copies all the data from the previous version to the new version when the application is started up. This gives you a hook to migrate any of the data from one version to the next. This is good for in memory databases like Sql Lite or SQL CE.

One thing that I cam across is that when you have a large amount of data (4 gig) if you store it in the Data Directory this data will be copied from the old version to the new version. This will slow down the start up time after an upgrade. If you have a large amount of data or you don't want to worry about migrating data you can either store the data in the users local folder providing you have full trust or you can use isolated storage if you have a partial trust.

Isolated Storage

Local User Application Data

Bronumski
  • 14,009
  • 6
  • 49
  • 77
  • Thankyou for this Bronumski, this does iterate some of the problems I was facing, my data size is relatively small being no larger than around 50MB. – Brett Ryan Jul 21 '11 at 03:40
  • 3
    Also, it doesn't carry the data forward if you have created new files. It only carries data that is deployed forward to the next version. – RobinDotNet Aug 01 '11 at 20:10