Mise à Jour du Moteur de Recherche des Arrêts de Bus de Montréal

This post is also available in english here.

Jusqu'à présent, les retours ont été bons pour mon petit utilitaire de recherche des arrêts de bus à Montréal, malgré que je ne fasse pas activement de publicité.

Pour utiliser de la terminologie Microsoft, je "dogfood" ma propre application, et j'ai trouvé quelque points à améliorer un peu :

  • A présent, si l'on utilise Google Gears, on n'est plus redirigé automatiquement vers la liste des arrêts de la position courante. Il est simplement affiché une petite carte Google de l'endroit trouvé, et un bouton qui permet d'utiliser cette position.
  • Quelques messages d'erreur sont affichés si des données incorrectes ou manquantes sont entrées. Cela pouvait être perturbant de ne pas avoir de message...
  • Toutes les cartes utilisent maintenant la totalité de la largeur de l'écran. Cela évite d'avoir des cartes mal redimensionnées sur un écran mobile. Je me demande d'ailleurs ce que cela va donner sur un iPhone....
  • J'ai corrigé légèrement l'affichage des distances en Km au lieu de metres lorsque cela est approprié, bien que si vous êtes dans une autre ville que Montréal, vous verrez probablement une trèèès grande distance s'afficher.
    Je me demande toujours si je dois filtrer les personnes qui sont hors de Montréal. Le but de ce site est aussi d'être une démo technologique de la Géo Localisation, donc même la distance est inutilisable, sa présence est malgré tout importante.
  • J'ai aussi ajouté quelques exemples de noms de rues pour aides les visiteurs qui ne sont pas de Montréal à voir ce que ce site peut faire. J'ai sélectionne au hasard une intersection et un numéro d'arrêt de bus qui peuvent être utilisés directement.
  • J'ai aussi fait une petite passe de validation XHTML, histoire d'être un peu compatible... :)

Maintenant, je pense que je vais essayer de m'assurer que la recherche Google va trouver le site en Anglais et Français. Pour l'instant, je vais avoir les mêmes problèmes que les pages du site pour logiciel Bluetooth Remote Control. Google parcours les pages des sites sans préciser de langue, et donc pour ce site, c'est l'anglais qui va sortir en premier puisque c'est le langage par défaut. J'ajouterais probablement un "/fr" et "/en" en base virtuelle pour chacun d'eux.

Comme toujours, si vous avez des suggestions ou rapports de bugs, je suis intéressé !

L'attribut InternalsVisibleTo en .NET 2.0 et les Assemblies Non Signées

Posté le mardi 2 septembre 2008 15:30 par jay :: 0 commentaire(s)
Classé sous

This post is available in english here.

Dans un récent projet, dans le but de faire du test unitaire, j'ai du utiliser l'attribut InternalsVisibleTo ,  qui étend la portée du qualificateur internal. Cela permet de séparer le code de test unitaire de l'assembly principale, et ainsi éviter de publier le code de test unitaire ou de publier les classes internes dans le simple but de pouvoir les tester.

C'est un attribut très intéressant à plusieurs titres, mais en l'utilisant, vous pourriez tomber face à ce message :

error CS1726: Friend assembly reference 'Dummy' is invalid. Strong-name signed assemblies must specify a public key in their InternalsVisibleTo declarations.

Le problème est que mes deux assemblies source et destination n'étaient pas signées. J'ai alors essayé d'ajouter un "faux" PublicKey ou PublicKeyToken comme suggéré ici et ici, mais comme beaucoup de monde, je ne veux pas m'encombrer avec la signature des assemblies pour le moment dans mon projet.

En fait, il se trouve que le compilateur considère l'assembly source comme "signée" si l'un des deux attributs AssemblyKeyFile ou AssemblyKeyName sont présents, même ils sont vides.

Donc, pour pouvoir utiliser l'attribut InternalsVisibleTo avec des assemblies non signées, enlevez simplement les attibuts AssemblyKeyFile et AssemblyKeyName si vous ne les utilisez pas.

Utiliser Google Gears Pour Trouver Les Arrêts de Bus de l'île de Montréal

This post is available in english here.

(Si vous ne voulez pas lire tout l'article, voici le site en question : http://jaylee.org/stm)

Cela fait un moment que je n'ai pas posté sur ce blog. Cette fois, je ne parlerais pas de Bluetooth, mais quand même de code .NET :)

J'ai été très occupé récemment, mais j'ai trouvé un peu de temps pour travailler sur un outil qui va m'aider beaucoup, et qui va aider beaucoup d'utilisateurs de Windows Mobile et d'utilisateur d'internet mobile en général (à Montréal).

Le réseau de Bus de Montréal est relativement grand, mais sa représentation dans le monde digital est plus que pauvre, et inexistante lorsque l'on parle d'internet mobile. Le site Web en question génère de très grosses pages qui ne sont pas adaptées à la navigation mobile.

La plupart du temps, il s'agit simplement d'avoir l'horaire du prochain bus, et c'est plutôt compliqué en utilisant les outils existants.

Il y a eu quelques initiatives récemment sur iPhone, et je voulais donner l'opportunité aux autre utilisateurs d'avoir les mêmes informations plus rapidement, avec un petit plus de Géo-Locatisation.

C'est la que Google Gears entre en action, où leur dernière mise à jour offre une API de Geo-Localisation qui donne une position approximative en utilisant les antennes GSM les plus proches. Malheureusement, cela ne fonctionne que sous Windows Mobile. Mais ne vous en faites pas, ce la fonctionne malgré tout ! Vous aurez simplement à taper un peu au clavier pour entrer l'intersection de rues la plus proche.

Après avoir récupéré la position, l'outil interroge une base de données (en utilisant Linq to SQL) pour récupérer l'arrêt de bus le plus proche, ainsi que le prochain horaire. J'interroge également Google Maps pour avoir une carte avec quelques marqueurs pour visualiser les arrêts. Cela peut-être utile, car la 'triangulation' par GSM est plutôt imprécise par nature.

Il est également possible de demander les horaires d'un arrêt de bus en particulier, en utilisant le numéro de l'arrêt précisé sur les panneaux. Le petit plus ici, par rapport au site original, est que les horaires passés de moins d'une demi heure aussi sont affichés, au cas où une rue en grande ligne droite permette de savoir si un bus est passé ou pas, et donc si il est simplement en retard.

Enfin, si vous êtes à Montréal et que vous avez une connexion internet mobile (ou standard), visitez le site à cette adresse : http://jaylee.org/stm

Tous commentaires ou suggestions sont les bienvenus !

ILogicalThreadAffinative, suite.

Posté le jeudi 15 mai 2008 04:09 par jay :: 0 commentaire(s)
Classé sous , ,

This post is also available in english here .

Dans un précédent post, je parlais d'une fonctionnalité du Framework .NET qui permet de passer des informations automatiquement d'une thread vers toute autre thread qu'elle crée.

En fait, le contexte d'appel passe non seulement aux Threads du Thread Pool, mais également à toute instance de System.Threading.Timer et aux IO Completion Threads, comme celle utilisées avec les sockets.

J'ai été surpris par le fait que dans les premiers étages du pipeline remoting coté serveur, il y avait des informations dans le CallContext et ce bien avant que le message entrant n'ai été interprété. Mais cela n'était pas tout à fait ce à quoi je m'attendais; c'était des données qui étaient présentes dans le contexte d'appel lors de l'appel à RemotingConfiguration.Configure().

Cela prend du sens, puisque tous les sockets utilisés par le TcpChannel et HttpChannel sont créés lors de l'appel à cette méthode, et des opérations asynchrones sont démarrées à ce moment la. Donc, pour éviter d'avoir les données qui transitent de l'autre coté, il y a ces deux méthodes sur la classe ExecutionContext pour supprimer et restaurer le passage du context d'appel.

IEnumerable<T>.Any() vs. IEnumerable<T>.Count() != 0

Posté le dimanche 11 mai 2008 00:15 par jay :: 2 commentaire(s)
Classé sous , ,

An english version is available here .

Après avoir lu ce post d'Eric Lippert, je me suis rappelé que dans l'exemple de ce post, j'utilise IEnumerable<T>.Count() ou je ne me sers pas vraiment la valeur de retour, et du coup, mon code énumère la totalité de la collection inutilement.

J'aurais pu utiliser IEnumerable<T>.Any(), qui après avoir regardé le code IL, démarre simplement l'énumération et s'arrête juste après un élément puis retourne true, ou si il n'y a rien, retourne false.

Bien plus efficace, à défaut d'utiliser PLinq !

Aventures avec le mot clé "let" dans LINQ to Objects

Posté le samedi 10 mai 2008 17:35 par jay :: 3 commentaire(s)
Classé sous , ,

This post is also available in english here .

Je me suis finalement décidé à blogger dans les deux langues, français et anglais. BlogEngine.NET ne me permet pas d'écrire mes posts dans les deux langues, et après avoir fait quelques essais de site multilingue sur la même url, il se trouve que Google n'indexe pas vraiment très bien ce genre de contenu dynamique.

Quoi qu'il en soit, j'ai eu le temps dernièrement de jouer avec LINQ to objects, et en particulier avec le mot clé "let".

J'avais un grand nombre de fichiers XML placés dans des répertoires multiples, et je voulais les filtrer avec une expression régulière. D'abord, voici comment j'ai récupéré tous les fichiers dans mes répertoires :

  var files = from dir in Directory.GetDirectories(rootPath, SearchOption.AllDirectories)
              from file in Directory.GetFiles("", "*.*")
              select new { Path = dir, File = Path.GetFileName(file) };

Arrivé à ce point, j'aurais pu éviter d'utiliser Directory.GetDirectories puisque GetFiles permet également de chercher recursivement. Mais puisque GetFiles ne retourne qu'un seul tableau de String et non un énumérateur, cela aurait voulu dire que tous mes fichiers auraient été retournées en un seul tableau, ce qui n'est pas très efficace en terme de consommation mémoire. J'aurais préféré avoir une implémentation de GetDirectories et GetFiles basée sur un itérateur, mais la plus fine énumération ne peut être faite que comme ca, sans appel vers du code natif.

Ensuite, ayant tous mes fichiers, je voulais à présent les filtrer en utilisant une expression régulière, puisque les fichiers que je voulais analyser suivaient un format de nom spécifique. J'ai donc mis à jour ma requête comme suit :

    Regex match = new Regex(@"(?<value>\d{4}).xml");
    var files2 = from dir in Directory.GetDirectories(args[0], "*", SearchOption.AllDirectories)
                 from file in Directory.GetFiles(dir, "*.xml")
                 let r = match.Match(Path.GetFileName(file))
                 where r.Success
                 select new {
                    Path = dir,
                    File = Path.GetFileName(file),
                    Value = r.Groups["value"].Value
                 };

Cette fois, j'ai introduit le mot clé let. Ce mot clé est intéressant puisqu'il permet la création d'une variable locale à la requête qui peut contenir à la fois des collections ou des objets simples. Le contenu de cette variable peut être réutilisé dans la clause where, comme source d'une autre requête from, ou dans le select.

Dans mon cas, je voulais simplement avoir le résultat de l'évaluation de mon expression régulière, donc j'ai simplement appelé Regex.Match pour valider le nom du fichier. Enfin, je place le contenu d'un groupe de l'expression dans le type anonyme résultant.

Avec tous mes fichiers filtrés, j'ai constaté ensuite que certains n'étaient pas valides puisqu'il ne contenaient pas un noeud XML spécifique. J'ai adapté ma requête comme cela :

    var files2 = from dir in Directory.GetDirectories(args[0], "*", SearchOption.AllDirectories)
                 from file in Directory.GetFiles(dir, "*.xml")
                 let r = match.Match(Path.GetFileName(file))
                 let c = XElement.Load(file).XPathSelectElements("
//dummy")
                 where r.Success && c.Count() != 0
                 select new {
                    Path = dir,
                    File = Path.GetFileName(file),
                    Value = r.Groups["value"].Value
                 };

J'ai ajouté un nouveau let pour me permettre de charger le document XML, et m'assurer que le noeud nommé "dummy" existe quelque part dans le codument. Au passage, si vous cherchez XPath dans XLinq, regardez par ici.

Vous vous demandez peut-être quand le XElement.Load est effectivement évalué... et bien il n'est sulement évalué lors de l'appel du c.Count(), qui ne l'est que lorsque la regex a validé le fichier concerné. De cette manière, je ne suis pas en train d'essayer de charger tous les fichiers retournés par GetFiles. Il faut se rappeler que les requêtes LINQ ne sont évaluées que lorsqu'elles sont énumérées.

En conclusion, LINQ est une technologie particulierement intéressante, et définitivement pas seulement réservée pour l'interrogation de bases de données. Ce que j'apprécie le plus et qu'il est possible d'écrire du code pratiquement sans boucles, ce qui permet de réduire les effets de bord.

Si vous n'avez pas jeté un coup d'oeuil sur LINQ, essayez, vous aprécierez probablement !

.NET Threads, CallContext et ILogicalThreadAffinative

This post is also available in english here .

J'ai récemment cherché un moyen de passer automatiquement des informations du contexte d'appel d'une thread vers tout autre thread créée à partir de la première. Cela peut-être utile pour de multiples raison, comme par exemple avoir des informations contextuelles placées dans le TLS à propos de l'utilisateur courant, ou pour tout autre information contextuelle spécifique à l'application.

Il est possible d'obtenir ce comportement en entourant le point d'entrée d'une thread de code qui va passer les informations à la nouvelle thread. C'est généralement assez fastidieux, voire complexe lorsqu'il s'agit de passer des informations générées en interne par un framework, puisqu'il faut absolument intercepter toutes les créations de thread.

Il existe un moyen pour faire cela en utilisant la class CallContext, et en particulier les méthodes GetData/SetData. Le problème est que si l'on place des données dans le CallContext, elles ne seront pas passées à une nouvelle thread. En pratique, pour que les données soient passées, il suffit que l'objet placé dans le CallContext implémente l'interface ILogicalThreadAffinative.

C'est une sorte d'interface marqueur qui permet d'éviter de faire transiter des données entre Threads lorsqu'elle n'y sont pas destinées.

Il est également intéressant de noter que les types marqués avec ILogicalThreadAffinative seront passés aux threads créées par le Thread Pool, et donc aux delegates placés dans la queue par l'appel à la méthode BeginInvoke qui est générée par le compilateur C#.

Enfin, dans le cas d'un appel distant en Remoting, tout type marqué avec ILogicalThreadAffinative sera sérialisé vers le contexte d'appel distant, puis sérialisé à nouveau en retour vers le contexte local.

Etre capable de faire du pas-à-pas dans le code du Framework a été d'une grande aide pour comprendre tout cela ;)

Mon autre blog...

Comme j'écris principalement en anglais, je me suis décidé à le déplacer sur mon propre site à cette adresse : www.jaylee.org

Je continuerais peut-être à poster quelques articles en francais ici, mais beaucoup moins souvent.

En ce moment, il s'agit principalement des mes pensées sur WPF, avec lequel je m'amuse beaucoup :)

See you around !

ODP.NET 10.2.0.2.20 Connection Pool Race Condition

Aaah, les joies d'Oracle. Ma base de données préférée... accompagnée de son cortège de bugs...

Bon, j'arrête là le sarcasme, mais j'ai du mal :)

Dans le cadre d'un projet sur lequel je travaille, je suis tombé sur un bug très, très gênant : Le provider ODP.NET d'oracle peut se connecter à un schéma sur lequel il n'est pas censé se connecter...

Je m'explique : dans le même AppDomain d'un même process, je crée dans des Threads différentes deux OracleConnection avec deux chaines de connexion différentes. Jusque là , rien d'anormal. Le problème est que de temps à autres, l'une de deux connexion va utiliser la chaine de l'autre thread !

Après avoir vérifé rapidement le contenu de l'objet OracleConnection, il se trouve qu'une variable nommée "m_InternalConStr" contient parfois une chaine qui ne correspond par du tout à celle qui a été passée en paramètre dans le constructeur... C'est très génant, car si l'on se connecte à une base alors que l'on pense se connecter à une autre, ... je vous laisse immaginer les dégats si on fait des updates.

Donc après de nombreuses tentatives, je suis arrivé à la conclusion qu'il faut synchroniser tous les appels à OracleConnection du constructeur jusqu'à Open avec un Mutex, et cela sur l'AppDomain courant. Vous imaginez aisément le goulot d'étranglement. J'aurais tout aussi bien pu désactiver le Connection Pool, mais la aussi, coté performance cela devient gênant.

Bien entendu, ce genre de problème apparait plus souvent sur une machine Multi Processeur. (En production dans mon cas, ca fait toujours plaisir...)

Je n'arrive pas à reproduire la Race Condition de manière systématique, mais je met avec ce post un exemple de code qui teste tout ca. Généralement, l'erreur apparait au bout de quelques essais. Pour tester si le ConnectionPool est consistant, j'effectue quelques lignes de Reflection pour aller chercher des variables interne... pas très propre, mais c'est suffisement déterministe.

Si quelqu'un se sent suffisement motivé pour tester... :)

Bluetooth Remote Control 0.5.0-Beta5

Voici une nouvelle version de Bluetooth Remote Control for Windows Mobile, avec quelques petites améliorations :

  • L'installation du fichier CAB automatique,
  • Correction de quelques problèmes de stabilité sur SPV E200,
  • La possibilité de visualiser les notes d'un slide PowerPoint sur le PPC/SmartPhone.

La version 0.5.0-Beta5 est disponible ici :

http://jaylee.org/remotecontrol

--

Here is a new version of Bluetooth Remote Control for Windows Mobile, with some improvements :

  • Automatic installation of the CAB file,
  • The correction of some stability issues on SPV E200,
  • The ability to view slide notes in PowerPoint on the PPC/SmartPhone.

The version 0.5.0-Beta5 is available here :

http://jaylee.org/remotecontrol

C# 3.0, a sneak peek

If you've used both DataSet and DataTable, you must have seen the DataTable.Select method. This is an interesting method that allows to select rows using a set of criterias, like IS NULL and comparison operators referencing columns of the current table, as well as columns from other tables using relations. The problem with method is that is returns a DataRow[], on which you cannot perform an other select.

The solution is actually quite simple : Just copy the rows you'll answer me. Yes, but you can't just reference rows in two DataTable instances, so you also have to perform a deep copy of the rows. So, with a little digging in the DataTable methods, here is what you get :

public static DataTable Select(DataTable table, string filter, string sort)
{
   DataRow[] rows = table.Select(filter, sort);
   DataTable outputTable = table.Clone();

   outputTable.BeginLoadData();

   foreach(DataRow row in rows)
      outputTable.LoadDataRow(row.ItemArray, true);

   outputTable.EndLoadData();
   return outputTable;
}

Clone is used to copy the table schema only, BeginLoadData/EndLoadData to disable any event processing during the load operation, and LoadDataRow to effectively load each row. This seems to be a fairly fast way to copy a table's data.

Now, I wondered how they would do this in C# 3.0, since there is a lot of data manipulation with the new LINQ syntax. This version is quite interesting because instead of evolving the runtime, they chose to upgrade only the language by adding features that generate a lot of code under the hood. That was the case in C# 2.0 with iterators and anonymous methods. C# 1.0 also had this with foreach, using or lock for instance.

In the particular case of Linq, C# 3.0 generates a method invocation list  of a LINQ query, producing standard C# 3.0 code with the help of lambda expressions. For example, these two lines are equivalent :

   var query = from a in test where a > 2 select a;
   var query2 = Sequence.Where(test, a => a > 2);

This ties a little more the compiler to the system asssemblies, but this does not matter anymore.

By the way, you can apply queries to standard arrays and join them :

static void Main(string[] args)
{
   var names = new[] {
      new { Id=0, name="test" },
      new { Id=1, name="test1" },
      new { Id=2, name="test2" },
      new { Id=4, name="test2" },
   };

   var addresses = new[] {
      new { Id=0, address="address" },
      new { Id=1, address="address1" },
      new { Id=2, address="address2" },
      new { Id=3, address="address2" },
   };

   var query = from name in names
      join address in addresses on name.Id equals address.Id
      orderby name.name
      select new {name = name.name, address = address.address};

   foreach(var value in query)
      Console.WriteLine(value);
}

I've joined the two arrays using the Id field, and creating a new type that extracts both name and address. I really like inline querying because you can query anything that implements IEnumerable.

I'm also wondering how it'll fit into eSQL (Entity SQL)...

But back to the original subject of this post. They had to do some kind of a DataTable copy in the C# 3.0 helper library, which uses extension methods :

   DataTableExtensions.ToDataTable<T>(IEnumerable<T>)

And with some further digging, I found that the LoadDataRow method for copying data is the fastest way to go.

I also found out using the great reflector that there is an Expression compiler in System.Expressions.Expression<T>. Maybe they finally did expose an expression parser that we can use... I'll try this one too !

SourceSafe and Explicit Error Messages

Aaaahhh, Visual SourceSafe, my favorite software. Maybe more than Toad. Especially when I get the most explicit and out of context message "File not found" during an archive restore using the admin GUI tool. That reminds me of the unix-style error messages... What a mess.

Anyway, if during a SourceSafe archive restore you get that error and you've already done more than once a full analyze of your source base, then you might want to try the command line utility ssrestor to do this.

Yeah I know, Florent, I'd better switch to Team System, but beleive me I'm trying :)

First thoughts on Windows Vista CPP Beta 2

Windows Vista Beta 2 has been released a few weeks ago, and I though it was about time for me to give it a try.

Clean installation has been pretty long, mainly because I've burnt the OS ISO Image on a DVD-RW disc, which is not particularly fast. It almost took an hour to complete, but after that the machine is usable. Almost no user input, just at the beginning for the partitions, locale and Product Key and again at the end for the locale.

I'm testing on a Dell Latitude D820 with a NVidia Quadro 120M, and the official drivers from NVidia do not support this one. However, with a little bit of tweaking in the inf file of the driver, Vista is able to enable the sleek Aero glass UI, which is pretty neat ! I like to be able to look through the taskbar, and to use the 3D task switcher. It's also interesting to see pixel shaders in action on something else but a game. I'm a little bit curious to see what kind of UI graphic designers are going to create... Imagine something like a fish tank around your windows :) Ok, that'd be pretty annoying, but you get the picture.

This build of Windows Vista includes the Windows Media Center. This is a cool peace of software but there are some bugs left, like the mouse not in synch with the actual clicks on the screen, or the Aero look disapearing for a while when a run it on my second screen. I don't know who to blame for the latter, but I think it would be because of my hack around the video driver.

The system is pretty responsive, even with the Aero UI enabled. I'd have expected it to be far less responsive considering the whole bunch of new features pressuring the system. It still has some slowdowns here and there, but I can't figure out why. Vista features ReadyBoost, which allows the system to "cache" the page file on a USB Flash Drive. Since a flash drive is about 10 times the speed of the hard drive, it speeds up the read of evicted memory pages. With this feature enabled, I find the system more responsive and applications are returning far more rapidly. I'll be trying to do some charts on overall system speedup. Intel SpeedStep is also natively used, the processor frequency is changing when the cpu usage increases.

I also had some bluescreens during the boot, and with the help of WinDBG, I figured out it was the USB driver that was faulty. Not that it actually is the USB driver, but rather the USB Audio driver I have that is messing up the system. It's not a Windows Vista compliant, so I'm not surprised...

Also around system performance, Vista maintains a performance index, which allows to see if system performance, like booting, is degrading, steady or improving. It also gives you what kind of device driver slows the boot or standby process, and an history of the changes on the system.

About mouting ISO images, Daemon Tools 3.33 - the latest version crashes the system - allowed me to install Visual Studio 2005, and SQL Server client tools SP1, which also both run fine. The only application that does work as well as on XP is VLC, which forces Vista to fall back in visual compatibility mode where aero is disabled. I'll try to talk about applications compatibility in a future post.

Mass storage does not seem to have changed at lot, though there is now the possibility to shrink or extend online partitions. When you shrink a volume, it only allows you to remove the free space at the end of the volume, and does not seem to defragment or compact it. Anyway, a long time missing feature...

Networking seems to have improved a lot under the hood, for what I can read about. The only part that held my eyes is the IPv6 support with, for the first time, a UI to configure it. Wifi's working like a charm.

On the mobile side, the "so-called" Windows Mobile Device Center is nothing more than ActiveSync in disguise. Dialogs are a prettier, but I really hope this will not stay the same crap it is now.

Last, the Windows Explorer has a lot of improvements, like the copy files dialog which now gives an optional throughput in MB/s and total size, or easy file filtering in the column headers. There is also a feature that allows to fully or partially restore a previous version of a folder. This is a really interesting feature that kind of legitimates a 500GB hard drive for a secretary computer ;) It will certainly bring out some security problems, but it's nice it exists.

 

Overall, I'm neither amazed nor disapointed in Windows Vista. I've read that the latest build fixes a lot of the slowness, and on a Core Duo 2.0GHz, to my perception, it does not run as fast as XP does. I'll wait for the RC1 to fix my mind :)

BTRemote Control and Windows XP 64 Bits

Quite a few people have now been using the latest beta for a while, and I get most of the time feature requests, sometimes non critical bugs like the Remote Client not connecting if the host PC is not discoverable, and not so often blocking bugs.

The one Krijn Wijnands (thanks !) has uncovered might involve Windows XP 64 Bits. The remote client does not connect to the server, and he's using an hardware configuration that's proved to work fine.

I do not own a 64 bits machine and if any of readers of this blog or user of this utility uses Windows XP 64 bits, please leave me a message. I'll be glad to hear from you.

The client version of this software do log much out of the debug build for now, but I'll add some more for extensive diagnostics.

From a pure developer point of view, .NET 2.0 64 Bits should not change a thing, but I suspect a P/Invoke issue that I've not covered. That should give me a reason to upgrade my server to 64 Bits ;) For the sake of the testing, of course.

For the next release, I'll be adding generic support for applications, configurable using a static xml file (there's no point on modifying this at runtime)

If you have some other wishes that come to mind, feel free to speak !

Long time, no see !

I know, it's been a while. Schedule's been hard to catch up to, but I now get enough time to blog a little... So here are some news about what I did the past several months:

  • A new release of Bluetooth Remote Control for Windows Mobile, which now supports QVGA screens, and uses a lil' bit of .NET 2.0 on the desktop. It is still in beta phase, since there's been a lot of changes under the hood. I've had some testers running it with QTEK 9100/Orange M3000 (HTC Wizard clones) and SPV C600. So far, a few bugs reported, and feature requests like support for the Windows Media Center. About the latter, since I've been playing with the Beta2 CPP of Windows Vista, I'll be adding support for this one, hoping it'll work with previous releases.
  • Still playing with my Terratec T² (a DVB-T tuner), trying to build some kind of an RTSP server, broadcasting on my LAN using multicast. I've been able to multicast a DVB-T multiplex on my network, playing it back with VLC. I even got to play both H264 Test HD1 and Test HD2 streams (10.5 mpbs each, compared to the 5mbps of SD streams). Though, I had a hard time changing the tuning frequency, mainly because the Terratec BDA driver seems to need a full DShow graph set up, needing MPEG-2 filters that I don't use anyway, which took me time to figure out.
  • I also worked on a project to correlate GSM antennas to GPS coordinates, a lot like CellTrack, the original idea being the software mostly on .NET and working on my QTEK 9100. This also led me to use the GPS API provided by Windows CE 5, which works pretty well, except when the GPS loses its power and sorta freezes the underlying serial GPS stack. Anyway, worth a look if you don't want to decode NMEA sentences by hand.
  • Finally, I'm working on the remote reading of water meters for Suez-Environment. Quite an interesting project which involves processing a important amount of data coming from water meters.

That's it for now :)

I'll certainly be blogging a bit more about the Remote Control software, since this is what I'm motivated the most to work on right now.

Precision Timer in .NET 2.0

If you've been using the .NET Framework since the beginning, you must have had to do some early code profiling, or framerate computation for realtime graphics.

The first idea that pops up to acheive this is to use the DateTime.Now property and do some subtraction of two instances. This is not a good idea since the resolution of this timer is around 10ms or so, which is clearly not enough (and your framerate counter may not go higher than 100 FPS or worse may not work at all).

If you've been in the business for long enough, and been doing some plain old "native" code in, say, C++ on Win32, you should probably used the couple QueryPerformanceFrequency/QueryPerformanceCounter to get the job done. And the same goes for .NET 1.0/1.1. Well, I don't know for you, but each time I have a project that reaches a certain critical size, I always need to use this kind of timer and I end up by writing the P/Invoke wrapper to reach these two methods.

Good news is, .NET 2.0 already has this class integrated in the form of System.Diagnostics.Stopwatch, so you don't have to write it from scratch again and again because you can't find on the net the right "free" class that does enough for you.

The BCL team has added some other nice utility classes like this one, and this saves quite some time.

Moving my Blog around...

Hi everyone,

I'm moving my blog here at CodeS-SourceS, since Florent Santin (and the admin I don't know, thanks btw) has been kind enough to give me a blog here. All my previous posts are still there, but I'll now be posting here.

Since I'm a .NET enthusiast, most of my posts are and still will be around .NET, C# 2.0 and 3.0 (and not VB.NET), the .NET Compact Framework I used to develop Bluetooth Remote Control, and some other stuff I'm working on.

Right now, my focus is mostly on .NET 2.0, its generics, anonymous methods, iterators and LCG to get the most out of it.

I'll also post about a litte utility I'm working on to have a clone of the nice CellTrack software for the SPV C500/C600 to work on the HTC Wizard clones (M3000, QTEK 9100, IMate K-Jam). It's now working quite nicely, especially when coupled with a GPS receiver...

Anyways, stay tuned for more .NET stuff :)

IIS, HTTP 401.3 and ASP.NET directories ACLs

A few days ago, on a newly installed web server with all the appropriate security patches applied, I kept having the same error on every ASP.NET 1.1 application I was running :

HTTP Error 401.3 - Unauthorized: Access is denied due to an ACL set on the requested resource.

At first, the reflex is to check all the permissions of the mapped physical directory, that they match the Application Pool identity, the guest identity (IUSR_Machine on my server) and for some configurations, the impersonated identity any ASP.NET configuration. Even with all these checks, any ASP.NET application was returning the same 401.3 error for anonymous users...

Well, it turns out that the ACL of the %SystemRoot%\Microsoft.NET\Framework\v1.1.4322 is important too... I don't know how the ACL got changed in the first place, and I don't know either how I came to check on these ACL, but that can waste a lot of time...

Sharing Visual Studio 2005 Settings.settings File across Assemblies

A new feature of the Visual Studio 2005 is the introduction of the Setting.settings file, which generates a class that maps your application configuration file. This avoids creating this class by yourself, and it supports updating and saving. What is is more interesting is that WebServices automatically add their WSDL locations in there, as well as data connection strings.

There is a problem though when you let VS2005 create the file by itself in a multi-assembly setup, where it creates a settings.settings for a "dll" packaged assembly. You end up with one settings.settings file for each of your assemblies, which is particularily not useful.

So, because there's a solution, you just have to share the only settings.setting file that matters to your application and here's how :

  • Remove the settings.settings file from all your assemblies, except the one that will be the master.
  • Add the master settings.settings file as a linked file in each of your projects, and you're done.

Just in case you've never linked a file in VS, when you're about to add the file to your project, just click on the little arrow next to the open button and select Link File. The magic after this is that VS2005 uses the linked file as if it were a local file.

One last note : Don't forget to copy all your existing settings from each assemblies to your master settings file.

Reflective Visitor vs. Meta Visitor

In a previous post, Johan explained us how he managed to get the visitor design pattern to work without having to redefine visitable methods in the visitor base class. This is quite interesting for some reasons :

  • This is the edge of C++ programming, few know how to use templates like this,
  • The choice of the method to execute is done at compile time, avoiding the runtime type checking implied with the Reflective version and this is good for speed of code execution.

However, there are a few issues. The Meta Visitor does not handle passing parameters like the Reflective one does. Even if it did, I expect the templated code to dramatically increase to a point where a normal human beeing is having a hard time reading it, along with giving a really hard time for the compiler to get to the end of it...

Anyway, I'm pretty confident about Johan ending up with a longer blog with a solution to this issue. (No stress Proppy, really :))

I'm a pragmatic developer, I try to consider all the aspects of the development and I tend to prefer readability over technically challenging code. But there's a place for everyone and researchers are here to make things go further away... Go, Go, Go proppy ;)


Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01