Freitag, 23. September 2011

SQLite, Visual C++ and migration from .NET 3.5 to .NET 4.0

Recently we migrated our .NET 3.5 based projects to .NET 4.0. With a little self written tool that changes the framework version in the .csproj files (there are a lot of them) and a little maual work the job was quickly done. But then came the testing of the setup made up of the new files. This was were the tragedy began.

New Version of System.Data.SQLite for .NET 4.0
We had problems with the System.Data.SQLite.dll we were using. We found out that you need a new version of the dlls for .NET 4.0 (can be downloaded from the vendors page). That was the easy one.

32 bit or 64 bit
The .NET 4.0 dlls did not fix our issues. Next thing we assumed was the commonly known point that this product does not support AnyCPU compilation, because it is a wrapper around the C library of SQLite. So we assumed we had a x86 / x64 issue. But this was not the case either.

Here come the solution
The point was, that with the .NET 4.0 version of SQLite the Visual C++ runtime seems to be a prerequisite. On our development machines everything worked well due to the installed Visual Studio. But on the setup machines SQLite did not work. So if you migrate from .NET 3.5 to .NET 4.0 and use SQLite, make sure the C++ runtime is installed.


  • Visual C++ Redistributable package 32 bit
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x86]
    Installed = 1 (REG_DWORD)
  • Visual C++ 2010 Redistributable package 64 bit
    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\VC\VCRedist\x64]
    Installed = 1 (REG_DWORD)
Found this, besides some other useful hints here, but noticed that the 64bit registry key was slightly wrong, so be aware of that.

Native .NET SQLite
A different approach would be to use the native .NET SQLite port that can be found here. The project is not officially related to SQLite, but it is based on a current version of SQLite of 3.7.7.1. The project seems to be quite active. I hope I will be able to try it out some time. Does anyone have experiences with that?


Dienstag, 28. Juni 2011

Der Out-of-browser Schock

Ich habe unlängst versucht eine bestehende Silverlight Applikation "Out-of-browser" zu bringen. Die Applikation verwendet eine Art Bootstrapper der im Application_Startup Ereigniss gestartet wird. Dieser Bootstrapper führt eine Reihe von Serviceaufrufen durch um bestimmte Initialisierungen vorzunehmen und Daten zu laden die mein Client später braucht.

Als "In-Browser" Applikation läuft das alles super. Out-of-Browser läuft nichts mehr. Ich bekomme TimeoutExceptions bei einfachen, kurzen Serviceoperationen. Bei meinen Recherechen bin ich mehrfach auch einen Hinweis wie diesen gestoßen:

http://stackoverflow.com/questions/5432286/cross-domain-policies-in-silverlight-out-of-browser

Es handelt sich bei dem Problem nicht um ein Cross-Domain Problem - dann hätte man als Exception ja auch eher eine SecurityException erwartet.

Der Grund scheint zu sein: in einer OOB Applikation kann am aus dem Application_Startup Ereignis keine Services aufrufen bevor das Root Visual gesetzt ist. Die genannte Lösung ist, diesen Code in das Loaded-Ereignis des RootVisual zu schreiben.

Tatsächlich hilft es, das RootVisual zunächst auf ein UserControl zu setzen. Dann werden auch Serviceaufrufe aus der App.xaml.cs heraus ausgeführt. Leider kann man das RootVisual nur einmal setzen. Spätere Setzungen werden einfach ignoriert.

Ungeachtet der Tatasache ob es möglich wäre, die Applikation so umzubauen das die Serviceaufrufe erst nach der Setzung des RootVisuals erfolgen frage ich mich warum das überhaupt sein muss? Warum schafft man so einen strukturellen Unterschied zwischen In-Browser und OOB? Ich hatte gehofft das eine App "einfach so" auch Out of Browser läuft - solange sie nicht die HTML-Bridge benutzt, das versteht sich von selbst.

Ich finde es sehr schade das dies offenbar nicht möglich ist...

Anbei die Punkte die mir bei der Umstellung von In-Browser auf OOB aufgefallen sind:
  • Vor dem ersten Servicecall muss das RootVisual gesetzt werden
  • Vor der Nutzung von HtmlPage sollte mit HtmlPage.IsEnabled geprüft werden ob die HTML Bridge verfügbar ist.
Weitere Punkte werde ich ergänzen so wie sie mir auffallen :-)

Donnerstag, 24. Februar 2011

Multi Targeting mit WPF und Silverlight

Multi Targeting hilft, Code in WPF und Silverlight gemeinsam zu verwenden. Im Rahmen der BASTA Spring 2011 hatte ich die Gelegenheit einen Vortrag zu diesem spannenden Thema zu halten.

Für alle die teilgenommen haben oder die nicht Teilnehmen konnten, stelle ich hier die Demos und Folien des Vortrags zum download bereit. Ich hoffe allen Teilnehmern hat der Vortrag gefallen und ich hoffe das Sie praktische Tips mitnehmen konnten.

Der Download enthält einige Links, die komplette Demo aus dem Vortrag, die Slides und die Projekt Linker Extension für Visual Studio.

Falls Sie Fragen zu den Demos oder Folien haben, melden Sie sich einfach bei mir.

Download

Montag, 10. Januar 2011

IIS, ASP.NET 2.0 und .NET 4.0 Assemblies

Nach dem Austausch einiger Dateien innerhalb eines virtuellen IIS Verzeichnisses das Services hosted, ereilte mich folgende Fehlermeldung:

Die Datei oder Assembly "..." oder eine Abhängigkeit davon wurde nicht gefunden. Die Assembly wird von einer Laufzeit erstellt, die aktueller als die derzeit geladene Laufzeit ist, und kann nicht geladen werden.
Die Webseite welche die Services hosted basiert noch auf ASP.NET 2.0. Wie sich herausgestellt hat, ist eine Assembly die bereits auf das .NET Framework 4 als Zielframework kompiliert war mit in den "bin"-Ordner gerutscht, in dem die Assemblies für die Services lagen.

Obwohl die .NET 4.0 Assembly in keiner anderen Assmebly referenziert oder sonst wie verwendet wird, kommt es zu dem Fehler. Es scheint, das alle Assemblies geladen werden die im bin-Ordner liegen. Die Lösung war in diesem Fall also einfach: entferene die Assembly und alles ist gut.

Fazit: .NET 4.0 - ganz oder gar nicht :-)

Dienstag, 2. November 2010

Multithreading leicht gemacht...

Neulich ist mir eine sehr schlanke Metode bewusst geworden, mehere Aufgaben parallel anzustoßen und diese am Ende einer Methode wieder zu synchronisieren..

Ein Szenario dazu: in einer Methode möchte ich drei parallele Aufgaben anstoßen. Während diese laufen habe ich selber noch ein bisschen Arbeit zu erledigen. Am Ende der Methode brauche ich dann die Ergebnisse der parallelen Aktionen.

Die erste Idee dazu sind natürlich Threads. Also, wie war das nochmal... Thread-Objekt, da kommt ein ThreadStart (oder ParameterizedThreadStart) rein. Mh... der nimmt als Thread-Code aber nur ein Action-Delegate. Ich wollte aber eigenltich auch eine Funktion ausführen, oder eine Action mit mehreren Parametern. Kriegt man natürlich alles hin - Wrapper-Methoden, mehrere Parameter in eine einzelnes Objekt verpacken und so weiter. Unter dem Strich sind solche Lösungen aber immer etwas unhandlich.

Die weitaus einfachere Lösung basiert intern natürlich auch auf Threads. Diese erstelle ich aber nicht selber. Sondern ich nutze einfach das Async-Pattern. Silverlight-Entwicklern dürfte dieses Muster schon begegnet sein, weil alle Serviceaufrufe auf diesem Muster basieren. Einen ausgezeichneten Blogpost zum Thema gibt es hier.

Folgende Punkte am Async-Pattern sind für die Lösung interessant:
  1. Man benötigt ein Delegate für seine Methode. Das Delegate stellt die Methoden Begin- / EndInvoke bereit. Die Standard Func / Action Delegates dürften für die meisten Fälle ausreichen.
  2. Man muss BeginInvoke kein Callback übergeben, der Parameter darf null sein.
  3. Bei Verwendung generischer Action- / Func-Delegates verlangt die BeginInvoke-Methode typsichere Parameterwerte.
  4. EndInvoke ist eine blockierende Methode - falls noch kein Ergebnis vorliegt wartet die Methode solange bis das der Fall ist.
Besonders interessant sind aus meiner Sicht die Punkte 2 und 4 in Kombination.

Ein bisschen Code sagt mehr als tausend Worte, also:

class Program
  {
    static void Main(string[] args)
    {
      // Delegates holen
      Func<long> CountAFunc = CountA;
      Action<int> WriteCAction = WriteC;

      // Asynchron aufrufen - keine Callbacks, wir wollen die Ergebnisse gleich hier haben.
      IAsyncResult CountAAsyncResult = CountAFunc.BeginInvoke(null, null);
      IAsyncResult WriteCAsyncResult = WriteCAction.BeginInvoke(100, null, null);

      // Selber was arbeiten
      Thread.Sleep(10 * 1000);

      // Auf asynchrone Ergebnisse warten - EndInvoke ist blockierend!
      long CountAResult = CountAFunc.EndInvoke(CountAAsyncResult);
      WriteCAction.EndInvoke(WriteCAsyncResult);

      // Ergebnisse ausgeben
      Console.WriteLine("CountAResult " + CountAResult);
      Console.ReadLine();
    }

    public static long CountA()
    {
      long Result = 0;

      for (int i = 0; i < 1000; i++)
      {
        Result += i;
        Console.WriteLine("A " + i);
        Thread.Sleep(10);
      }

      return Result;
    }

    public static void WriteC(int Start)
    {
      for (int i = Start; i < 1000; i++)
      {
        Console.WriteLine("C " + i);
        Thread.Sleep(10);
      }

    }
  }


Ich habe zweieinfache Methoden die asynchron ausgeführt werden sollen: CountA und WriteC. Erstere ist eine parameterlose Function die (umständlich) die Summe der Zahlen von 1 - 999 berechnet. Die zweite Zählt von einem Startwert bis 1000. Beide Methoden erzeugen noch eine Ausgabe auf der Konsole.

Zu den beiden Methoden beschafft man sich Delegates, ruft diese mit BeginInvoke auf. Dann erledigt man seine eigene Arbeit (hier einfach 10 sek. warten). Dann sammelt man mit EndInvoke auf den Delegates die tatsächlichen Ergebnisse ein und gibt diese aus.

Mulitthreading leicht gemacht! Mehr zum Thema gibt es in der MSDN.

Viel Spaß!