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.

Advertisements

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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

iReadable { }

.NET Tips & Tricks

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Ricos Blog zu Softwaredesign- und architektur

Ideen und Gedanken rund um Softwaredesign und -architektur, Domain-Driven Design, C# und Windows Azure

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

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

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: