C# .NET Tutorial 8: Working with Isolated Storage
Welcome to number 8 of this C# tutorial series. Today we will discuss working with isolated storage. With the emergence of viruses, malware, and spyware developers know that applications working in a sandbox of limited access is better for users. However applications sometimes need to store state data and this represents a problem for applications running on restricted priveleges. It would be nice if we had a place where applications can store information that is safe to use without having to test whether the application has enough rights to save data to the hard drive. The .NET Framework provides a solution for this. This is isolated storage. With isolated storage an application can save data without having to worry whether it is running in partial, limited, or full trust.
IsolatedStorageFile Class
The IsolatedStorageFile class provides the mechanism to create files and folders in isolated storage. These are the most important static methods of this class:
- GetMachineStoreForApplication – retrieves a machine-level store for the called Click-Once application.
- GetMachineStoreForAssembly – retrieves a machine-level store for the assembly that called.
- GetMachineStoreForDomain – retrieves a machine-level store for the AppDomain within the current assembly that called.
- GetStore – retrieves stores based on the IsolatedStorageScope enumerator.
- GetUserStoreForApplication – retrieves a user-level store for the called Click-Once application.
- GetUserStoreForAssembly – retrieves a user-level store for the assembly that called.
- GetUserStoreForDomain – retrieves a user-level store for the AppDomain within the current assembly that called.
The following are the most important IsolatedStorageFile properties:
- ApplicationIdentity – The Click-Once application’s identity that scopes the isolated storage.
- AssemblyIdentity – The assembly’s identity that scopes the isolated storage.
- CurrentSize – the size of the current data stored in the isolated storage.
- MaximumSize – the maximum storage size of the isolated storage.
- DomainIdentity – the identity of the AppDomain that scopes the isolated storage.
- Scope – the IsolatedStorageScope enumeration value that describes the scope of this isolated storage.
These are the commonly used IsolatedStorageFile methods:
- Close – closes an instance of the store.
- CreateDirectory – creates a directory within the store.
- DeleteDirectory – deletes a directory within the store.
- DeleteFile – deletes a file within the store.
- GetDirectoryNames – gets a list of directory names within the store that match a file mask.
- GetFileNames – gets a list of file names within the store that match a file mask.
- Remove – removes the entire store from the current system.
Note: Click-Once applications are new types of applications (in .NET 2.0) that are meant to be deployed and installed from web pages. These new type of applications are meant to solve deployment of applications across a large company. For more info click here.
How to Create a Store
Before saving data in isolated storage one needs to determine the scope for the data in the store. For most applications you normally choose one of the following two methods:
- Assembly/Machine – this method creates a store to keep information that is specific to the calling assembly and the local machine. It is well suited for application-level data.
- Assembly/User – this method creates a store to keep information that is specific to the calling assembly and the current user. It is well suited for user-level data.
To create one of the following you use the following code:
//Assembly/Machine store IsolatedStorageFile myStorage = IsolatedStorageFile.GetMachineStoreForAssembly(); //Assembly/User store IsolatedStorageFile myStorage = IsolatedStorageFile.GetUserStoreForAssembly();
For Click-Once deployed applications one can use an application-level store that supports both a machine-level store and a user-level store. This only works with Click-Once applications because the executing assembly has its own evidence that might or might not be valid for local applications.
IsolatedStorageFileStream Class
The IsolatedStorageFileStream encapsulates a stream that is used to create files in isolated storage. It derives from the FileStream class and therefore its properties and methods are the same.
Reading and Writing data to Isolated Storage
To create data within isolated storage you do it through the IsolatedStorageFileStream class. You create a new instance of the class specifying a relative file name and a store. Here is theĀ code.
//create a store
IsolatedStorageFile myStorage = IsolatedStorageFile.GetUserStoreForAssembly();
//create an isolated storage file stream
IsolatedStorageFileStream userStream = new IsolatedStorageFileStream("UserSettings.dat", FileMode.Create, userStore);
Working with the IsolatedStorageFileStream is just like working with any other stream. The following code provides an example.
//wrap IsolatedStorageFileStream to a StreamWriter
StreamWriter writer = new StreamWriter(userStream);
writer.WriteLine("UserName = Mark");
writer.Close();
Reading is also done in a very similar way. The only difference is that you need to change the FileMode to Open as shown here.
IsolatedStorageFileStream userStream = new IsolatedStorageFileStream("UserSettings.dat", FileMode.Open, userStore);
The only difference from the other streams is that the Isolated Storage does not support checking for the existing of files directly like File.Exists. To do this you need to use the following code:
string[] files = userStore.GetFileNames("UserSettings.dat");
if (files.length == 0)
Console.WriteLine("File not found");
else
Console.WriteLine("File found");
How to use Directories in Isolated Storage
In isolated storage one can also create directories as shown in this code:
userStore.CreateDirectory("TestDirectory");
IsolatedStorageFileStream userStream = new IsolatedStorageFileStream(
@"TestDirectory/UserSettings.dat",FileMode.Create, userStore);
To check for existence of directories you need to use the following code:
string[] directories = userStore.GetDirectoryNames("TestDirectory");
if (directories.length == 0)
{
//directory not found
}
else
{
//
}
The IsolatedStorageFilePermission Class
The IsolatedStorageFilePermission class encapsulates the permission that can be granted to code to allow it to access isolated storage. The following are the important properties:
- UsageAllowed – gets or sets the type of usage allowed.
- UserQuota – gets or sets the overall size of storage allowed per user.
Isolated Storage and Permissions
Before an assembly or application uses the isolated storage it needs the necessary permissions. Demanding permission can be accomplished by annotating your class or method with the IsolatedStorageFilePermission as shown here.
[IsolatedStorageFilePermission(SecurityAction.Demand)]
class Example
{
}
This ensures that any calls to work with isolated storage within this class willl succeed. This permission also supports several attributes that can be used to modify how isolated storage is used as shown below.
[IsolatedStorageFilePermission(SecurityAction.Demand, UserQuota=1024, UsageAllowed=IsolatedStorageContainment.AssemblyIsolataionByUser)]
class Example
{
}
Well that’s all for today! In the next two tutorials we will focus on text, specifically searching, modifying, and encoding text. In the next tutorial we will turn our attention to regular expressions in C#. See you soon!
Hi!
Nice post.
I’m using IsolatedStorageFile for saving application data.
How can I prevent loosing association to the IsolatedStorageFile if the Assemply will be renamed or moved from the first-run location?
1) c:\Test.exe –> save data
2) renaming c:\Test.exe in c:\Foo.exe
3) Foo.exe neds a new IsolatedStorageFile
Tnx in advance
To be able to use the same IsolatedStorage you need to use IsolatedStorageFile.GetMachineStoreForAssembly method to obtain the isolated storage because essentially it is still the same assembly.
I might be reading it wrong, but it looks like one of your examples is incorrect.
Under the Reading and Writing data to isolated storage your first example reads:
//create a store
IsolatedStorageFile myStorage = IsolatedStorageFile.GetUserStoreForAssembly();
//create an isolated storage file stream
IsolatedStorageFileStream userStream = new IsolatedStorageFileStream(“UserSettings.dat”, FileMode.Create, userStore);
In your constructor (last param) userStore should be myStorage. So it should read
//create a store
IsolatedStorageFile myStorage = IsolatedStorageFile.GetUserStoreForAssembly();
//create an isolated storage file stream
IsolatedStorageFileStream userStream = new IsolatedStorageFileStream(“UserSettings.dat”, FileMode.Create, myStorage);