Donnerstag, 24. Juli 2008

SuSE and Compose tables

This will probably need some explanation. I use a German keyboard (you only get those easily in Germany), but I use the US keyboard layout, because it's faster for things like {}[] (which you need a lot while programming) or @. But, often, I need German characters like 'ä' anyway.

Now, for this, Linux has an easy solution: the Compose key. It was a matter of minutes to configure SuSE / X / Gnome so that the Caps Lock key is used as a compose key, and I can use <Caps Lock><s><s> to get 'ß'.

But for 'ä', I needed to press <Caps Lock><:><a>, and that is much too awkward, because you need the Shift key for the ':'. I wanted to use <a><e> for this (by default configured to produce 'æ'). How hard could it be to change the compose table? Well, it took me some hours ...

The reason is that I first and for a long time looked at kbd. SuSE has even some settings in YAST for the kbd compose tables. But no matter what I did, the tables in /usr/share/kbd/keymaps/include just didn't change anything. Probably they are only used without X. The right tables to be changed are at /usr/share/X11/locale, and the one I needed was in the subdirectory en_US.UTF-8. Phew.

BTW, for Windows there is an open source freeware tool called AllChars, which does exactly the same and is very easy to configure.


Updating Linux

Support for SuSE 10.0 has ended ... (well, IMO a bit early, MS still support W2k). So, to get new security patches and other updates (e.g. Firefox 3), I had to update my operating system.

I first tried Ubuntu 8.01. Unfortunately, it not only made a buggy and unstable impression (couldn't use ntp properly (apparently a Gnome configuration problem), download of ATI drivers resulted in a 404, configuration dialogs freezing), but it also was very slow in startup and during network usage. Possibly a WLan driver issue.

So I gave up and installed SuSE 11.0. That worked rather well, because of good backups (and hey, Firefox and Thunderbird really can store everything in /home and use it for new versions; great job there). The only issue is that I can't get compiz to work with my xinerama settings (notebook and an external LCD monitor configured to be one big screen). It seems as if compiz always thinks that the desktop has a much smaller width then in reality ... doesn't repaint the background after a certain vertical line, can't resize windows beyond that line. An update of the display drivers didn't help (oh, and BTW, sax2 doesn't work with the new ATI drivers, had to use aticonfig). Setting the output sizes in the compiz configuration didn't help. Updating compiz lead to it not working at all (only white rectangles instead of windows). Oh well, I didn't have compiz before, I don't have it now, so no loss.

More annoying is that still a restart of the X window system is required if I wish to switch the external monitor on or off. Possibly an architectural problem there ... but Windows XP shows how to do it: I plug the monitor in, I have a bigger desktop. I remove the monitor, I have a smaller desktop. No re-configuration required, no logout required.


Donnerstag, 17. Juli 2008

Binding failures in mixed-mode applications

In .NET applications, assemblies are often loaded dynamically as soon as they are needed. This is not only true for explicitly loaded assemblies (via Assembly.Load), but also for other assemblies linked 'statically'.

In a pure .NET application, if such an assembly doesn't exist (perhaps because the user messed up his installation and deleted the file), an exception is thrown, which you can catch and handle appropriately (e.g. with an error message to the user).

In a mixed-mode application, having a native main program which uses some .NET components, things are more complicated. In my case, the .NET assembly is linked to the program with the #using directive (you could also use the project settings, but #using has the advantage that only the necessary files are recompiled if the assembly changes). This means that it will get loaded as soon as managed code from the corresponding object file is executed.
But typically, that code is called from unmanaged code. There is no place to put a try / catch for the binding failure!

If you don't do anything at all about this, your application may crash with a cryptic (to the user) message dialog, perhaps containing the Windows error code for .NET exceptions (0xE0434F4D). Not very helpful. What can you do?
  • Try to use a global 'unhandled exception handler' or a try / catch on a more global level. Unfortunately, while the binding failure propagates to your handler, it can cause other exceptions. In my case, a STATUS_SXS_INVALID_DEACTIVATION, which is even more cryptic.
  • Always call the code of the file with the #using directive only from managed code. Which means that you have to remember to insert otherwise useless wrapper functions in other source files just so that the exception can be caught. Definitely not a nice solution.
  • Perhaps you can use MDAs? Indeed, they fire also in this situation. But (quite apart from the problem that they must be enabled globally in the registry or through an environment variable) there is no good API to handle MDA messages. There is one in the .NET hosting interfaces (ICLROnEventManager), but do you want to host the CLR just for this? Certainly not.
  • Try to load the required assemblies yourself before they are loaded automatically. Then you can catch the binding failure and do what you like. This also is not a nice solution, but at least the code for that is not very large and locally confined. You just have to remember to adapt it if you add or remove an assembly, or update it to a new version (for signed assemblies).
The last one is the way I chose. I'm still not happy with it - you shouldn't have to do this test yourself - but I can't think of anything better. If you have many signed assemblies which often change their version and can't adapt the code automatically, however, the solution won't be good for you either. In my case, most assemblies always have the same version as the main application (they are versioned automatically by the automatic build), so that's no problem for me.


Samstag, 12. Juli 2008

Ein neuer Blog

Lange hatte ich keine Motivation, ein Blog anzufangen. Warum auch? Es gibt schon (zu?) viele davon, und wenig, was ich an Neuem beitragen kann.

In letzter Zeit bin ich aber speziell im Bereich der Software-Entwicklung hin und wieder auf Dinge gestoßen, die im Netz noch kaum oder nur unklar zu finden waren, und die vielleicht auch für andere von Interesse sein könnten. Und wer weiß, vielleicht schreibe ich ja dann auch zu anderen Themen, wenn schon ein Blog da ist ...

Warum 'Gedankenwelten'? Weil ein Blog aus Gedanken besteht, die Blogosphäre daher viele Gedankenwelten darstellt - und weil ich Fantasy mag, bei der ein großer Reiz daher kommt, dass sie Gedankenwelten aufstellt.

Posts zur Software-Entwicklung werde ich in Englisch abfassen, den Rest in Deutsch.