Using isolated storage for application-specific data in C# .NET

There’s a special storage location for a .NET application on Windows that is allocated to that application. It’s called isolated storage and it’s an optimal place to store files by an application that doesn’t have full access to the file system. Writing to and reading from isolated storage doesn’t require any extra security check. An application without full access to the file system will be able to use its allocated slot in isolated storage and nothing else. It’s an ideal mechanism for storing e.g. application state.

However, don’t confuse isolated storage with file security. It is still a “normal” location on disk with a file path. A typical location is under users/[username]/appdata/local. Therefore you or full-trust applications can still find and modify the files saved in isolated storage. However, limited-trust applications won’t be able to access any other part of the file system.

The two key objects into isolated storage are IsolatedStorageFile and IsolatedStorageFileStream. Let’s see how a custom AppSettings object can be saved for a user in isolated storage:

private static void SaveSettingsInIsoStorage()
{
	IsolatedStorageFile applicationStorageFileForUser = IsolatedStorageFile.GetUserStoreForAssembly();
	IsolatedStorageFileStream applicationStorageStreamForUser = new IsolatedStorageFileStream("settings.txt", FileMode.Create, applicationStorageFileForUser);
	AppSettings settings = new AppSettings()
	{
		Job = "Programmer",
		Language = "C#",
		Name = "Andras"
	};
	string contents = JsonConvert.SerializeObject(settings);

	using (StreamWriter sw = new StreamWriter(applicationStorageStreamForUser))
	{
		sw.WriteLine(contents);
	}
}

…where AppSettings looks like this:

public class AppSettings
{
	public string Language { get; set; }
	public string Name { get; set; }
	public string Job { get; set; }
}

We simply save the settings object as a JSON string in the assembly-specific section of the isolated storage at the user level. We can also store machine-wide settings for an application using the GetMachineStoreForAssembly method instead.

Reading from isolated is equally easy:

private static void ReadSettingsFromIsoStorage()
{
	IsolatedStorageFile applicationStorageFileForUser = IsolatedStorageFile.GetUserStoreForAssembly();
	IsolatedStorageFileStream applicationStorageStreamForUser = new IsolatedStorageFileStream("settings.txt", FileMode.Open, applicationStorageFileForUser);
	using (StreamReader sr = new StreamReader(applicationStorageStreamForUser))
	{
		string raw = sr.ReadLine();
		Debug.WriteLine(raw);
	}
}

Here’s the output:

{“Language”:”C#”,”Name”:”Andras”,”Job”:”Programmer”}

We’re not restricted to save files in isolated storage. We can also create folders for organisation purposes. It’s very easy to create a folder. The IsolatedStorageFileStream example is almost identical to what we saw in the code above. However, remember that the directory must be created first before you can save anything in it:

private static void SaveSettingsInIsoStorage()
{
	IsolatedStorageFile applicationStorageFileForUser = IsolatedStorageFile.GetUserStoreForAssembly();
	applicationStorageFileForUser.CreateDirectory("AppSettings");
	IsolatedStorageFileStream applicationStorageStreamForUser = new IsolatedStorageFileStream("AppSettings/settings.txt", FileMode.Create, applicationStorageFileForUser);
	AppSettings settings = new AppSettings()
	{
		Job = "Programmer",
		Language = "C#",
		Name = "Andras"
	};
	string contents = JsonConvert.SerializeObject(settings);

	using (StreamWriter sw = new StreamWriter(applicationStorageStreamForUser))
	{
		sw.WriteLine(contents);
	}
}

It can be a good idea to check whether the directory exists before you create it:

string[] directoryNames = applicationStorageFileForUser.GetDirectoryNames("AppSettings");
if (!directoryNames.Any())
{
	applicationStorageFileForUser.CreateDirectory("AppSettings");
}

There’s no property that lets you easily read the actual location on disk. You’ll need to set a breakpoint right after this line:

private static void SaveSettingsInIsoStorage()
{
	IsolatedStorageFile applicationStorageFileForUser = IsolatedStorageFile.GetUserStoreForAssembly();
...
}

When the code execution stops hover over “applicationStorageFileForUser” and open the “Non-public members” section. You’ll see a property called RootDirectory in the bottom of the list. The value should point to a user-specific location. In my case it is…

C:\Users\andras.nemes\AppData\Local\IsolatedStorage\nq213l1g.ul1\tflubnij.chu\Url.2ekkfnx05wuhzecg5x4y0q3tfifmqex4\AssemFiles\

…and there it is:

Isolated storage file location for user

Let’s change the code so that we save the settings at the machine level:

private static void SaveSettingsInIsoStorage()
{	
       IsolatedStorageFile assemblyStorageFileForMachine = IsolatedStorageFile.GetMachineStoreForAssembly();
...
}

The same hidden RootDirectory property will point to the ProgramData folder similar to the following:

C:\ProgramData\IsolatedStorage\ofau1sef.fzp\lchabgk0.ywi\Url.2ekkfnx05wuhzecg5x4y0q3tfifmqex4\AssemFiles\

Let’s check:

Isolated storage file location for machine

Miscellaneous

Every application that uses isolated storage has a defined quota in bytes that it can use. Normally the default quota for partially trusted applications, e.g. those that you download from the internet, is 1MB. The IsolatedStorageFile object exposes a couple of properties that describe the quota, the available space and the size used:

IsolatedStorageFile applicationStorageFileForUser = IsolatedStorageFile.GetUserStoreForAssembly();
			
Debug.WriteLine(applicationStorageFileForUser.AvailableFreeSpace);
Debug.WriteLine(applicationStorageFileForUser.Quota);
Debug.WriteLine(applicationStorageFileForUser.UsedSize);

If the quota is not enough you can request a new upper limit using the IncreaseQuotaTo method of the IsolatedStorageFile class:

bool quotaIncreaseSuccess = applicationStorageFileForUser.IncreaseQuotaTo(some number);

The method will throw an exception if you’re trying to reduce the quota, i.e. set a lower number than the current quota.

Read all posts dedicated to file I/O here.

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

One Response to Using isolated storage for application-specific data in C# .NET

  1. jfuri says:

    Is there a way to interact with isolated storage asynchronously?

Leave a comment

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.