Simple Dice Roller goes Mobile

Es ist soweit, meine erste WinPhone App ist zur Zertifizierung eingereicht!

Während der Simple Dice Roller einen Aufwand von gut einer Woche erfordert hatte, war der Mobile Dice Roller in etwa einem Tag fertig und das samt deutscher Lokalisierung. Viel von der Funktionalität der WinStore App konnte ich in eine Portable Library auslagern, ohne großartig Änderungen am Bestandscode durchführen zu müssen (portable Bibliotheken unterstützen nur eine Teilmenge der .NET-Funktionalitäten der verschiedenen Plattformen – den kleinsten gemeinsamen Nenner). Lediglich die Oberfläche musste ich neu entwerfen und dies fiel wegen der deutlich einfacheren Struktur einer Phone-Anwendung auch entsprechend leichter als bei den vielen Möglichkeiten einer Store-Anwendung. Die neuen Strukturen ermöglichen es nun, auch einfach eine deutsche Version des Simple Dice Rollers bereitzustellen, ohne dabei dort einen eigenen Weg gehen zu müssen.

Sobald der Simple Dice Roller: Mobile Edition zertifiziert und veröffentlicht wurde, werde ich hier den entsprechenden Link bereitstellen.

Erste Schritte: Windows Phone 8 Apps

Der Einstieg in die Windows Phone App-Programmierung fiel mir sehr viel einfacher als in die Windows Store App-Programmierung, was aber sicherlich an einer gewissen Ähnlichkeit liegt. Prinzipiell geht es auch hier um Seiten, zwischen denen navigiert wird. Interessant fand ich den relativ ähnlichen Ansatz zur Settings-Speicherung – beide arbeiten mit Dictionaries, die automatisch gespeichert werden.

Windows Store App

Object obj;
ApplicationDataContainer roamingSettings = ApplicationData.Current.RoamingSettings;
roamingSettings.Values.TryGetValue("Key", out obj);
...
roamingSettings.Values["Key"] = obj;

Windows Phone App

Object obj;
IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;
appSettings.TryGetValue("Key", out obj);
...
appSettings.Values["Key"] = obj;

Nokia Lumia 520

Seit kurzem bin ich stolzer Besitzer eines Lumia 520 (Windows Phone 8) – es besitzt zwar nicht die „Wertigkeit“ (Aussehen, Material, etc.) eines Samsung Galaxy, aber dafür überzeugt mich das Betriebssystem. Von Anfang an macht es Spaß damit zu arbeiten und die von Nokia mitgelieferten Apps (Karten, Navi, Musik/Radio Mix) gefallen. Nun sind auch alle Mails, Kontakte, etc. synchron auf Server, Notebook, Surface und Phone und das ohne großartige Installationen – einfach unproblematisch. Ich freue mich jetzt schon auf meine ersten Windows Phone Apps!

Eine Batch-Datei als Dienst ausführen?

Ohne Hilfsmittel geht das meines Wissens nicht. Aber warum will man das überhaupt? In diesem Fall möchte ich gerne den Minecraft-Server „Bukkit“ als Dienst auf einem anderen Rechner ausführen, um ihn dort automatisch mit dem System starten zu lassen und mit net start/stop einfach steuern zu können.

Im Netz werden einige Tools als „Service-Wrapper“ vorgeschlagen, aber da ich selbst mal swrap programmiert habe, nutze ich dieses Tool einfach mal (fürs erste). Leider fiel mir dabei auch gleich ein Bug auf, der über die Jahre nicht entdeckt wurde: Wenn die Registry den Basisschlüssel der Anwendung (unter HKEY_LOCAL_MACHINE\Software) nicht enthält, wird immer mit einem Initialisierungsfehler (SWERR_1) abgebrochen. Auf der anderen Seite ist es aber schön zu sehen, dass das Tool auch noch unter „Win8 64-bit“ out-of-the-box läuft.

Nach Ergänzung des Schlüssels „HKEY_LOCAL_MACHINE\Software\Wow6432Node\netShore\Services“ war der Rest einfach:

swrap /c "BUKKIT-Server" "cmd /c ""c:\bukkit server\run.bat"""

Dazu noch die „run.bat“ erweitern:

c:
cd "c:\bukkit server"
"c:\program files\java\jre6\bin\java.exe" ... -jar "c:\bukkit server\craftbukkit.jar" ...
pause

Und schon taucht „BUKKIT-Server“ im Dienstemanager auf und kann gestartet werden. Leider funktioniert hier das Beenden noch nicht, da „swrap“ den gestarteten Prozess (hier: cmd) beendet und nicht den durch die BAT-Datei gestarteten Java-Prozess. Für mein konkretes Problem werde ich über eine gezielte Implementierung eines Dienstes nachdenken. Das Grund-„Problem“ (Batch-Datei als Dienst ausführen) ist aber prinzipiell lösbar.

ASP.NET 4.5 auf IIS 7.5 mit SQL Server Express 2012 einrichten

Hier mein Vorgehen nach langem und frustrierendem Herumprobieren:

IIS vorbereiten

  1. Verzeichnis für App anlegen und App hineinkopieren
  2. App im IIS-Manager zum Beispiel als neue Site hinzufügen (mit eigenem AppPool)
  3. Anonyme Authentifizierung auf „AppPool-Identity“ festlegen
  4. AppPool-Grundeinstellungen auf .NET 4.0 (integriert) festlegen
  5. Erweiterte AppPool-Einstellungen auf „Benutzerprofil laden = True“ und „Identität = AppPool-Identity“ festlegen
  6. In der Kommandozeile folgende Befehle ausführen:
    icacls <app-path> /grant "IIS APPPOOL\<apppool-name>":(OI)(CI)(RX)
    icacls <app-path>\App_Data /grant "IIS APPPOOL\<apppool-name>":(OI)(CI)(F)

SQL Server vorbereiten

  1. Mit den folgenden Befehlen den SQL Server Express aktualisieren:
    CREATE LOGIN [IIS APPPOOL\<apppool-name>] FROM WINDOWS
    GRANT CREATE DATABASE TO [IIS APPPOOL\<apppool-name>]

Der passende Connection String

Beim Connection String kann es dann wieder etwas hakelig werden, aber der folgende Eintrag funktioniert ganz gut:
Data Source=.\SQLEXPRESS; Initial Catalog=<db-name>; Integrated Security=SSPI; AttachDBFilename=|DataDirectory|<db-name>.mdf; User Instance=true

IIS 7 + SQL Server Express 2008

Leider, leider scheint das bei dieser Kombo nicht so „einfach“ zu sein, denn mit „User Instance=true“ kommt es zu Impersonation-Fehlern und ohne fehlen die Rechte im App_Data-Verzeichnis…

Letzteres lässt sich aber korrigieren, indem man dem User „<host-name>\SQLServerMSSQLUser$<host-name>$SQLEXPRESS“ Vollzugriff auf App_Data gewährt – dann kann „User Instance“ komplett weggelassen werden.

WWW-Authenticate (Basic) in ASP.NET

Mit nur wenigen Zeilen lässt sich die Basic Authentication (http://de.wikipedia.org/wiki/HTTP-Authentifizierung) in C# umsetzen:

const String KEY = "BasicAuthKey";
const String Basic = "Basic ";

if (Session.Contents[KEY] == null)
{
    Response.BufferOutput = true;

    String auth = Request.Headers["Authorization"] ?? String.Empty;
    auth = System.Text.Encoding.UTF8.GetString(
        Convert.FromBase64String(auth.StartsWith(Basic)
        ? auth.Substring(Basic.Length) : String.Empty));
    if (auth == "username:password")
    {
        Session.Contents.Add(KEY, new Object());
    }
    else
    {
        Response.Clear();
        Response.Headers.Set(
            "WWW-Authenticate",
            "Basic realm=\"RegisteredUsers@domain.tld\"");
        Response.SetStatus(HttpStatusCode.Unauthorized);
        Response.End();
    }
}

SQL Server Express (localdb) per OleDB ansprechen

Der Zugriff auf die SQL Server Express 2012 Instanz „(localdb)\v11.0“ ist leider nicht über den OleDB-Provider „SQLOLEDB“ möglich. Stattdessen muss „SQLNCLI11“ (der Native Client) verwendet werden. Mit „Trusted_Connection=yes“ kann dann noch die Windows-Authentifizierung aktiviert werden. Der vollständige ConnectionString könnte dann so aussehen:

Provider=SQLNCLI11;
Data Source=(localdb)\v11.0;
Initial Catalog=<DB_NAME>;
Integrated Security=SSPI;
Trusted_Connection=yes;

SQL Server-Datenbank lässt sich nicht wiederherstellen

Das Wiederherstellen (RESTORE) einer auf einem SQL-Server (Standard 2008) gesicherten Datenbank auf einem anderen SQL-Server (Express 2012 – localdb\v11.0) führte heute bei mir zu Fehlermeldungen und Serverabstürzen. Ob neue Datenbank automatisch anlegen lassen oder in vorhandene importieren, machte keinen Unterschied – die MDF- und LDF-Dateien waren vorhanden und auch mit Daten gefüllt, aber die Datenbank ließ sich nicht laden. Leider wusste kein Forum von einer echten Lösung zu berichten, stattdessen wurde mit esoterischen Skripten aufgewartet, die rein gar nichts brachten. Ziemlich frustriert entschied ich mich dann dazu, den letzten Import per „Detach“ im Management Studio aus dem Server zu lösen und dann wieder per „Attach“ neu hinzuzufügen et voíla: die Datenbank war online!

StartSSL – kostenlose SSL-Zertifikate

SSL-Zertifikate müssen nichts kosten! StartSSL bietet einfache SSL-Zertifikate kostenlos an und das Verfahren ist einfach und schnell. Zum Nachweis, dass man eine Domain besitzt, erhält man einen Code wahlweise an hostmaster, postmaster oder webmaster@eigenedomain.tld zugesandt und erst nach Eingabe des Codes auf der StartSSL-Homepage geht es weiter.