Isolated Storage unter Microsofts Windows Phone 7

Windows Phone 7 unterscheidet sich in einem wesentlichen Punkt vom klassischen Windows Mobile, denn zu Gunsten der Systemsicherheit setzt Microsoft auf ein strikt gekapseltes Dateisystem. Dieser Isolated Storage erfordert ein spezielles Vorgehen, wenn Daten anwendungsübergreifend verarbeitet werden sollen.

Lesezeit: 18 Min.
In Pocket speichern
vorlesen Druckansicht Kommentare lesen 9 Beiträge
Von
  • Tam Hanna
Inhaltsverzeichnis

Windows Phone 7 unterscheidet sich in einem wesentlichen Punkt vom klassischen Windows Mobile, denn zu Gunsten der Systemsicherheit setzt Microsoft auf ein strikt gekapseltes Dateisystem. Dieser Isolated Storage erfordert ein spezielles Vorgehen, wenn Daten anwendungsübergreifend verarbeitet werden sollen.

Windows Mobile mag bei Endanwendern nie wirklich populär gewesen sein – Poweruser trauern dem (zugegebenermaßen komplexen) System bis heute nach. Es bot unter anderem ein vollwertiges Dateisystem für das Bearbeiten komplexer Sachverhalte mit mehreren Anwendungen. Das aktuelle Windows Phone 7 ist für Nicht-Poweruser optimiert. Aus diesem Grund hat Microsoft den Funktionsumfang frei nach dem Paretoprinzip radikal reduziert: Ein gemeinsames Dateisystem ist für gängige Anwendungen nicht nur unnötig, sondern sogar ein Sicherheitsrisiko.

Windows Phone 7 basiert auf Windows CE. Deshalb hat es intern ein echtes Dateisystem und arbeitet nicht wie Palm OS mit Datenbanken. Auch das als Applikationsframework verwendete .NET Compact Framework (.NET CF) kennt Dateien und Ordner. Die Isolationslösung von Microsoft arbeitet dabei wie ein "Jail". Jede Anwendung bekommt ihren eigenen, als Isolated Storage bezeichneten Ordner. In ihm kann man mit den diversen, von .NET am Desktop bekannten Klassen herumfuhrwerken.

Der Umgang mit Isolated Storage sei an einem kleinen Beispiel demonstriert (als Quellcode unter WP7Storage1 in den Programmbeispielen zum Artikel). Es speichert einen String im isolierten Speicher des Telefons oder Simulators und liest diesen bei Bedarf auch wieder aus. Die IsolatedStorageFile-Instanz sitzt in der Klasse und wird im Konstruktor mittels Aufruf von GetUserStoreForApplication() initialisiert. Es ist eines der Standardpattern in Windows Phone 7:

public partial class MainPage : PhoneApplicationPage
{
IsolatedStorageFile myISFile;
// Constructor
public MainPage()
{
InitializeComponent();
myISFile = IsolatedStorageFile.GetUserStoreForApplication();
}
Mehr Infos

Quellcode zum Artikel

Die für den Artikel erforderlichen Code- und Programmbeispiele finden Sie hier zum Download (.zip, 257 KByte).

Die Instanz von myISFile dient als alleiniges "Interface" zwischen Isolated Storage und Applikation. Man benutzt die Klasse auch zum Erstellen und Enumerieren von Ordnern. Nähere Informationen hierzu liefert die Spezifikation Klasse in der MSDN. In den Speicher wird sie wie folgt geladen:

private void CmdRead_Click(object sender, RoutedEventArgs e)
{
try
{
IsolatedStorageFileStream myStream =
new IsolatedStorageFileStream("settings.tmgn",
System.IO.FileMode.Open, myISFile);
StreamReader reader = new StreamReader(myStream);
textBox1.Text = reader.ReadToEnd();
reader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

Wie anhand des im Codebeispiel gezeigten Musters klar ersichtlich ist, erfolgt das Lesen und Speichern von Daten im Isolated Storage in der Regel über Dateiströme. Zum Speichern dient das folgende Codesegment (die Exception-Behandlung ist hier aus Platzgründen nicht enthalten). Über die Routine myISFile.DeleteFile("settings.tmgn"); lassen sich die Daten schließlich wieder löschen.

IsolatedStorageFileStream myStream = 
new IsolatedStorageFileStream("settings.tmgn",
System.IO.FileMode.Create, myISFile);
StreamWriter writer = new StreamWriter(myStream);
writer.Write(textBox1.Text);
writer.Close();

Um die Anwendung zu testen, kann man sowohl den Simulator als auch ein reales Gerät verwenden. Die IS-Beispiele sind unter Windows Phone 7.0 und 7.1 lauffähig. Will man den Isolated Storage der Anwendung komplett löschen, tappt man sie in der Programmliste des Mobilgeräts lang an und beendet die Anwendung.

Wer nur kleine Datenmengen speichert, scheut unter Umständen den Aufwand zum Serialisieren und Deserialisieren nach dem oben beschriebenen Schema. Die Klasse IsolatedStorageSettings schafft hier Abhilfe, dazu das Beispiel WP7Storage2. Hier soll die Klasse zum Speichern eines Strings verwendet werden. Im Konstruktor des Formulars belebt man dazu die als Membervariable der Klasse angelegte Variable mySettings mit einer Instanz von IsolatedStorageSettings:

public partial class MainPage : PhoneApplicationPage
{
IsolatedStorageSettings mySettings;
// Constructor
public MainPage()
{
InitializeComponent();
mySettings = IsolatedStorageSettings.ApplicationSettings;
}

Wie schon beim IsolatedStorageFile greift der Entwickler hier auf eine statische Funktion (in diesem Fall auf ein Member) der namengebenden Klasse zurück, um eine für das Beispiel verwendbare Instanz der Klasse zu erstellen. Diese Instanz dient sodann zum Lesen und Speichern der Werte. Dabei geht man nach dem Schema einer primitiven, flach strukturierten Registry vor: Das persistierte "Wörterbuch" enthält Schlüssel, die wiederum serialisierte Daten enthalten. Die Routine zum Abspeichern der Informationen:

private void CmdSave_Click(object sender, RoutedEventArgs e)
{
try
{
mySettings.Add("Textbox", textBox1.Text);
mySettings.Add("Slider", slider1.Value);
}
catch (ArgumentException ex)
{//Wert schon da
mySettings["Textbox"] = textBox1.Text;
mySettings["Slider"] = slider1.Value;
}
}

Die Routine versucht als Erstes, zwei neue Schlüssel im Wörterbuch anzulegen und mit den Werten zu füllen. Befinden sich die Schlüssel bereits im Wörterbuch, wirft die Runtime eine Exception, die im Catch-Block abgefangen wird. Hier greift man ganz klassisch auf die Daten zu und beschreibt mySettings wie ein Array. Statt Indizes übergibt man den Schlüsselnamen. Das Einlesen der Daten bietet ebenfalls wenig Überraschungen:

private void CmdRead_Click(object sender, RoutedEventArgs e)
{
try
{
textBox1.Text = (string)mySettings["Textbox"];
slider1.Value = (double)mySettings["Slider"];
}
catch (System.Collections.Generic.KeyNotFoundException ex)
{
MessageBox.Show(ex.Message);
}
}

Wie gewohnt beginnt die Routine mit einem Try-Catch-Block, der im Fall eines nicht vorhandenen Schlüssels eine Exception verhindert. In einem praktischen Programm sollten Entwickler im catch-Teil "vernünftige" Voreinstellungen wählen. Für das Einlesen der Werte können Entwickler erneut auf das übliche Array-Pattern zurückgreifen. Allerdings muss man die Werte casten, bevor man sie verwendet. Zum Löschen von Schlüsseln ruft man die Funktion Remove auf:

private void CmdRem_Click(object sender, RoutedEventArgs e)
{
mySettings.Remove("Textbox");
mySettings.Remove("Slider");
}