Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Use of Isolated Storage (A Simple Demo)

0.00/5 (No votes)
28 Jul 2008 2  
The article will help you to use Isolated Storage Classes

Introduction

Isolated Storage Namespace that is included in .NET Class Library is a good feature introduced in Visual Studio 2003 or later to hide certain data from the outside. The file where it actually stores those data is somewhat abstract to the user and also based on its scope specified while creating the application. In this article, I am going to discuss the basics of how to use Isolated Storage Classes and specify scope to those. The data stored through Isolated Storage is not accessible to Less trusted Applications, as they are scoped within the Assembly it produces.

The classes that we need in this project are listed below: 

  • IsolatedStorageFile: This is the Primary FileStream Object. It is the main class that manages directory, files and gets store for the assembly.
  • IsolatedStorageFileStream: Exposes a file within the Isolated file Location. It is the main File Stream object used for Reading or Writing on a File.
  • IsolatedStorageException: It is the exception object which is thrown when any Runtime exception is generated during Isolated file Operation.

We need to include System.IO.IsolatedStorage as well. Please note: The IsolatedStorage Classes are included in mscorlib.dll, which is automatically included. So no Reference is required.

Background

It is a very common practice to use Files to store sensitive information. Information like Web Service Path, User Settings, Application Settings are stored into Registry, config files or in some text files. The problem using them is that it does not belong to the Assembly itself, and thus should be exported whenever the assembly is exported.

Using Isolated Storage, we can include those data within the assembly itself, which will be automatically transmitted with that assembly. We may also write information to Application Data Blocks, System Files for better security. Use of Isolated Storage eliminates any Com unsecure applications to access that sensitive information.

Using the Code

This is a basic example of how we can write or fetch from an Isolated Storage. To do this, we need an object of IsolatedStorageFile. This class has a static function called GetStore. We can specify what type of Store we need.

Here is the list of all scopes available :

Members Name Description of the Use
None No Isolated Storage Usage
User Isolated Storage scoped to User Identity
Domain Isolated Storage Scoped to Application Domain Identity
Assembly Isolated Storage Scoped to Identity of the Assembly
Roaming The Isolated Storage Can roam.
Machine Isolated Storage Scoped to the Machine
Application Isolated Storage Scoped to the Application

Generally we use Domain as Application Scope, which identifies the Application Domain and stores data within the Application Domain.

Now it is time to understand the code.

As far as the basics are concerned, see the code below:

//Main Class that is used for Isolated Storage
using System;
using System.Windows.Forms;
using System.Text;
using System.IO;
using System.IO.IsolatedStorage;

namespace IsolatedStorage
{
    public partial class ISF : Form
    {
        private string filename;
        private string directoryname;
        IsolatedStorageFile isf = null;

        /// <summary>
        /// Constructor for ISF, Used generally for Initialization 
        /// </summary>
        public ISF()
        {
            filename = string.Empty;
            directoryname = string.Empty;
            InitializeComponent();
            isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User|
        IsolatedStorageScope.Assembly|IsolatedStorageScope.Domain, 
        typeof(System.Security.Policy.Url),typeof(System.Security.Policy.Url));
        }

        /// <summary>
        /// Invoked when Button1 is Clicked
        /// </summary>
        /// <param name="sender">Object that invokes the Event 
        /// ( Here it is Button1)</param>
        /// <param name="e">Event Related Arguments</param>
        private void button1_Click(object sender, EventArgs e)
        {
            LoadInfo();
        }

        /// <summary>
        /// Clear out Existing Loaded Information from the List Boxes
        /// </summary>
        private void LoadInfo()
        {
            lstDirectories.Items.Clear();
            lstFileList.Items.Clear();
            lstFileList.Items.AddRange(isf.GetFileNames("*"));
            lstDirectories.Items.AddRange(isf.GetDirectoryNames("*"));
        }

        /// <summary>
        /// Enabling btnSave when Text is Changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            btnSave.Enabled = true;
        }

        /// <summary>
        /// Called when Save button is clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                IsolatedStorageFileStream isfs;
                isfs = new IsolatedStorageFileStream(Path.Combine(getDirectoryName(), 
                        getFileName()), FileMode.Create, isf);
                byte[] data = Encoding.GetEncoding("utf-8").GetBytes(textBox1.Text);
                isfs.Write(data, 0, data.Length);
                isfs.Close();
                LoadInfo();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Runtime Error:" + ex.Message);
            }
        }

        /// <summary>
        /// Get Directory Name from the user of Session Context
        /// </summary>
        /// <returns></returns>
        private string getDirectoryName()
        {
            if (directoryname == string.Empty)
            {
                frmNewName dialog = new frmNewName();
                dialog.Text = "Enter Directory Name:";
                if (dialog.ShowDialog() == DialogResult.OK)
                    return dialog.Path;
                else
                    return string.Empty;

            }
            else
                return directoryname; 
        }

        /// <summary>
        /// Gets FileName from User or Current Session
        /// </summary>
        /// <returns></returns>
        private string getFileName()
        {
            if (filename == string.Empty)
            {
                frmNewName dialog = new frmNewName();
                dialog.Text = "Enter File Name:";
                if (dialog.ShowDialog() == DialogResult.OK)
                    return dialog.Path;
                else
                    return string.Empty;
            }
            else
                return filename;
        }

        /// <summary>
        /// Selected Index changed for File. Loads the File to the TextBox also
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstFileList_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                filename = lstFileList.SelectedItem.ToString();
                IsolatedStorageFileStream isfs = new IsolatedStorageFileStream
            (Path.Combine(directoryname,filename), FileMode.Open, isf);
                StreamReader sr = new StreamReader(isfs);
                textBox1.Text = sr.ReadToEnd();
                sr.Close();
                isfs.Close();
                btnSave.Enabled = false;
                lblItemStat.Text = Path.Combine(directoryname, filename);
            }
            catch (FileNotFoundException ex)
            {
                MessageBox.Show("Runtime Error:" + ex.Message);
            }
        }

        /// <summary>
        /// Creates New Directory
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnNewDir_Click(object sender, EventArgs e)
        {
            directoryname = string.Empty;
            directoryname = getDirectoryName();
            isf.CreateDirectory(directoryname);
            LoadInfo();
        }
        
        private void btnFile_Click(object sender, EventArgs e)
        {
            filename = string.Empty;
            filename = getFileName();
        }

        private void lstDirectories_SelectedIndexChanged(object sender, EventArgs e)
        {
            directoryname = lstDirectories.SelectedItem.ToString();  
            lstFileList.Items.Clear();
            lstFileList.Items.AddRange
		(isf.GetFileNames(Path.Combine(directoryname,"*")));
        }

        /// <summary>
        /// Removes currently selected Directory. Note It will 
        /// throw error if Directory is not Empty
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRemoveDir_Click(object sender, EventArgs e)
        {
            try
            {
                isf.DeleteDirectory(lstDirectories.SelectedItem.ToString());
                directoryname = string.Empty;
                LoadInfo();
            }
            catch (IsolatedStorageException ex)
            {
                MessageBox.Show("Runtime Error:" + ex.Message);
            }

        }
        /// <summary>
        /// Removes Chosen File
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRemoveFile_Click(object sender, EventArgs e)
        {
            try
            {
                isf.DeleteFile(Path.Combine(directoryname,
                    lstFileList.SelectedItem.ToString()));
                filename = string.Empty;
            }
            catch (IsolatedStorageException ex)
            {
                MessageBox.Show("Runtime Error:" + ex.Message);
            }
        }
    }
}        

This code might look a bit verbose to you. Ok, let us define it shortly.

To use Isolated Storage, we need to create a store for the data based on the scope we want. To get the store, we will write:

<>IsolatedStorageFile isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User|
        IsolatedStorageScope.Assembly|IsolatedStorageScope.Domain, null,null);>

In the above line, I have created an object of IsolatedStorage and got the store from Current User Domain.

After we get the Store, we need IsolatedStorageFileStream to read or write on a particular file.

IsolatedStorageFileStream isfs = new IsolatedStorageFileStream
                    ("abc.txt",FileMode.Create, isf);

In the above line, I have created on IsolatedStorageFileStream, which will create "abc.txt" file if it is not existing.

After doing so, we need StreamReader to read or StreamWriter to write on the file.

For reading from the file, we have to use FileMode.Open to ensure that it gives filenotfound error if the file is not found.

//For Reading

 StreamReader sr = new StreamReader(isfs);
 string fileData = sr.ReadToEnd();//Reads from the File it is pointed to

// For Writing

 StreamWriter sw = new StreamWriter(isfs);
 sw.WriteLine(fileData); // Writes Data to the File Opened

If the IO operation fails, it may throw IsolatedStorageException.

That's all we need. The others in the code are just to present you a good piece of interface.

Snapshots

coolImage1.JPG

In the above figure, it shows a button that invokes the Directory and Files to be loaded. The Button GetList will list all the directory and the Files stored in the current scope.

We may change scope to get other stores too.

coolimage2.JPG

The save button will save the file written on the Textbox to the chosen file. If no file is chosen yet, the file choose dialog box will be displayed.

coolImage3.JPG

The 3rd picture shows the dialog box that comes when the filename does not exist.

Try running the application and check. There may be some bugs on the application. I will fix them very soon.

Points of Interest

It's really fun to hide your important files from the user by including the feature of Isolated Storage classes. I think you all would have fun creating an application using this feature provided with .NET.

Functional Matrix

Instead of using GetStore function, you may also use the Custom functions provided with IsolatedStorageFile class. Here is the equivalence matrix:

IsolatedStorageFile.GetMachineStoreForApplication()

is equivalent to:

IsolatedStorageFile.GetStore(IsolatedStorageScope.Application | 
	IsolatedStorageScope.Machine, null, null);
IsolatedStorageFile.GetMachineStoreForAssembly()

is equivalent to:

IsolatedStorageFile.GetStore(IsolatedStorageScope.Assembly | 
IsolatedStorageScope.Machine, null, null);IsolatedStorageFile.GetMachineStoreForDomain()

is equivalent to:

IsolatedStorageFile.GetStore(IsolatedStorageScope.Assembly | 
	IsolatedStorageScope.Domain | IsolatedStorageScope.Machine, null, null);
IsolatedStorageFile.GetUserStoreForApplication() 

is equivalent to:

IsolatedStorageFile.GetStore(IsolatedStorageScope.Application | 
	IsolatedStorageScope.User, null); 
IsolatedStorageFile.GetUserStoreForAssembly()

is equivalent to:

IsolatedStorageFile.GetStore(IsolatedStorageScope.Assembly | 
	IsolatedStorageScope.User, null, null);
IsolatedStorageFile.GetUserStoreForDomain()

is equivalent to:

IsolatedStorageFile.GetStore(IsolatedStorageScope.Assembly | 
	IsolatedStorageScope.Domain | IsolatedStorageScope.User, null, null);

You can use any of these functions to get its store.

History

This is the first version of the article. I would like to update the application later to make it more handy.

First Version:  IsolatedStorage.zip - This is the first version of the Application. It may contain some bugs. I will fix them in future revisions. My intension is to give basic knowledge about the use of the system.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here