Saturday, December 31, 2005


Best wishes for 2006

2005 was a rich year in experiences, both professionally and personally. The money could be better so I am eating lentils to improve my situation in 2006 :-)

The end of the year was particularly busy any exciting, promising an interesting new year. I hope you had a great 2005 and will have an even better 2006.

Happy New Year!

Friday, December 30, 2005


Spammers killed my will to blog

No blogging this Christmas.

200+ spam comments per day took forever to clean up via the dial up connection I had during my (too short) vacation. The anti spam features I added to my blog last spring worked like a charm until I went away (Murphy's law). Very few, if any, spam posts made it through the system. Then the MT blacklist was taken off the air and I was left my backup solution based on regular expressions. It worked, but the system was only as good as the list of expressions used to validate post. Normally it was not a problem as I updated the list ASAP. The spammers changed tactics during Christmas; instead of one burst per day which I managed to handle, they started spamming a 24 hours a day.

I am back and I have blocked them, hopefully for good. The first thing I will do next year.... is to update my anti spam system so I can manage it from remote. I will blog my updated version when I have tuned it properly. It has a tarpit feature that slows down spammers but it also ties up valuable resources. Time will tell if it is a pain or a gain.
Enough whining. Back to my regular programming next week.

A Happy New Year to you all!

Thursday, December 15, 2005


Smart Paster plugin for Visual Studio

Shame on me for not posting about the Smart Paster 1.1 plugin before.

In Windows Forms applications I sometimes have to show long messages explaining why an operation failed or to provide additional information. The text is usually provided by the customer or a technical writer. Cutting and pasting it directly is normally not an option as:

  • the string is impossible to read in the editor or on paper when it is too long
  • there may be formatting characters which have to be escaped

XML and other text formats with quotes in them are even worse.

Unless you use Spart Paster that is;

The Smart Paster inserts the contents in a properly formatted String builder according to the configuration options:

Building XML the brutal way with string (i.e. not using XmlWriter) becomes a piece of cake. This source string in the clipboard:

 <node attribA="a" attribB="b"/>
 <path ="c:\temp\test.txt"/>

Automagically becomes this if you paste it as a StringBuilder called builder:

StringBuilder builder = new StringBuilder(81);
builder.AppendFormat(@"{0}", Environment.NewLine);
builder.AppendFormat(@"{0}{1}", ControlChars.Tab, Environment.NewLine);
builder.AppendFormat(@"{0}{1}", ControlChars.Tab, Environment.NewLine);
{0}", Environment.NewLine);

All quotes and strange characters taken care of. What more can you ask for?

Monday, December 12, 2005


Troubled waters ahead: changing telco provider

I am changing telco provider this week so my site and mail will go offline for a (hopefully) short time.

Friday, December 9, 2005


Error using SmtpMail: Could not access 'CDO.Message' object

I recently got a problem sending e-mail using System.Web.Mail.SmtpMail while implementing a system for notifying users that their password is about to expire. The SMTP server I was using supports authentication and .NET 1.1 automatically tries to log in if the server supports it. This is an edited network trace of the request that failed:

220 somehost Microsoft ESMTP MAIL Service, Version: 6.0.3790.1830 ready
EHLO egilh
250-somehost Hello []
<334 ...
<334 ...
<535 5.7.3 Authentication unsuccessful.

There is no properties for disabling automatic authentication, but you can control the behavior of the SMTP client using the Fields collection. The line in bold below shows how to control the authentication

System.Web.Mail.SmtpMail.SmtpServer = "10.10.*.*";
System.Web.Mail.MailMessage message = new System.Web.Mail.MailMessage();
message.From = "from@***.com";
message.Subject = "Mail subject";
message.To = "to@***.com";
message.Body = "And this is the body of the message";
// Set NO authentication (0=>none, 1=>basic, 2=>integrated)
message.Fields.Add("", 0);

The namespace allows you to control a lot of other features as well. The most useful ones:

  • sendusername: User name to authenticate with

  • sendpassword: Password to authenticate with

  • smtpconnectiontimeout: Set the connection time out

  • smtpserverport: Control which port is used

  • smtpusessl: Use SSL when sending mail

Thursday, December 8, 2005


Koders and CodeKeep plugins for .NET

A good code example is a great help when using a new API for the first time so I was pretty exited when Koders and CodeKeep released their plugins for Visual Studio. They take two different approaches:

  • CodeKeep searches private and public code sniplets

  • Koders searches a huge collection of source code

I like the idea behind CodeKeep as it works on code sniplets that does something useful and not a huge db of source code. CodeKeep only has a plugin in for Visual Studio .NET 2003 but versions for Visual Studio 2005 and Eclipse should be out soon.

Even though I like the idea, I quickly hit a big limitation: CodeKeep only searches by Description or Title. This is a problem as it requires you (and everyone else) to enter a good great description. It maybe useful for organizing your own code sniplets but searching for sniplets on how to use a particular API is difficult.

Koders take the other approach; they do not search the title or description but the code. With an ever growing code base it allows you to find an example for most APIs.

The Koders Visual Studio plugin installs a menu short cut and a small search toolbar. Versions for 2003 and Eclipse are available as well.

Both solutions are useful, but I would prefer mix that allows me to:

  • search by code when I know the API I have problems with. The code must have a brief description/title so I know if it applies to my context or not.

  • search by title/description/category when I know the problem but not the API.

  • view feedback and provide feedback. The more people that find the code useful the higher rank it will get

  • work with a local and internet solution. I am sure the "private/public" concept of CodeKeep works but I doubt if my clients would be happy if I posted their code on the internet

Monday, December 5, 2005


Mobility Developer Conference II (Milano)

The free Mobility Developer Conference II will be held in Milano Thursday 15/12/2005


  • Architecture of a mobile solution

  • Overview of Visual Studio 2005 and .NET Compact Framework 2.0

  • Strategies for exchanging information (MSMQ,Web Service, Socket, SQL CE, HTTP)

  • SQL Server 2005 Mobile Edition

  • The .NET Compact Framework connectivity APIs (SMS, Phone, Connection Manager, RAPI)

  • Tips and Tricks

See you there?


How to get detailed file information using VB Script

The script I posted yesterday showed how to get the size files using FileSystemObject. Windows Explorer displays a lot more information like the Dimensions of photos, Audio bit rates of audio files etc. The Shell.Application object can be used to extract the following information: Album Title, Artist, Attributes, Author, Bit Rate, Camera Model, Category, Comments, Company, Copyright, Date Accessed, Date Created, Date Modified, Date Picture Taken, Description, Dimensions, Duration, File Version, Genre, Name, Owner, Pages, Product Name, Product Version, Protected, Size, Status, Subject, Title, Track Number, Type, Year

The GetDetailsOf() method gets one of the properties above. They are extracted using an ID from 0 to 34. The following script from Microsoft Technet gets the name of each property and then looks up the values for all files in the c:\temp directory. 

' Get the name of the different properties
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace("C:\temp")
For i = 0 to 34
    arrHeaders(i) = objFolder.GetDetailsOf(objFolder.Items, i)
' Display the properties and their values for each file
For Each strFileName in objFolder.Items
    For i = 0 to 34
        Wscript.Echo i & vbtab & arrHeaders(i) _
            & ": " & objFolder.GetDetailsOf(strFileName, i)

The Windows Image Acquisition Automation Library v2.0 can be used if you need basic image acquisition and manipulation functionality.

Sunday, December 4, 2005


How to get the dimensions of files using the FileSystemObject

I got a question earlier this evening on how to get the dimensions of a file using the FileSystemObject. I put together the VBScript below that goes through all files of C:\ and lists the dimensions using the .Size property.

Option Explicit
'Purpose: List sub directories with files and their sizes
dim oFS
dim oDir
set oFS = CreateObject("Scripting.FileSystemObject")
set oDir = oFS.GetFolder("C:\")
listDir (oDir)
sub listDir(rootDir)
'Purpose: List contents of this directory and all subdirectories
dim oDir
dim oFile
    'Call ourselves for all sub directories
    WScript.echo rootDir.Path
    for each oDir in rootDir.SubFolders
        listDir (oDir)
    'List all the files in this directory
    for each oFile in rootDir.Files
        WScript.echo vbTab & & " [" & oFile.Size & " bytes]"
end sub

Saturday, December 3, 2005


Vodafone Live (Italy)

The latest release of vodafone live! (Italy) has taken away a lot of my time. The menu has moved to a different platform but the majority of the pages are still served by the platform where I am the software architect. After months of work it's nice to see it go live. With the latest generation devices you get a very rich user experience with background colors, tabbed navigation etc. as the following images show (sorry about the poor picture quality)

Home page:

Chat home page

A big step forward in terms of look and feel compared to what we released one year ago if you ask me.

I have recharged my batteries after the marathon release on the 1st of December so I should have the energy for posting something "useful" next week.

Friday, November 25, 2005


Milano: Linux Day 2005 in Cinisello Balsamo

Open Labs is organizing Linux Day 2005 Saturday 26/11 in Cinisello Balsamo. There are several presentations as well as a Demo Area and an Install Fest.

Be sure to bring empty CDs/DVDs or have a free partition if you want a hand from the experts at installing a linux flavor on your laptop. To be safe and can make sure that nothing goes wrong with your laptop, you can use the free VMPlayer and a base Virtual Machine.

Thanks for the tip Andrea!


Phase 1 of migration over

Mail, blog and web sites are all happily running on my laptop.

My server used a free MSDE DB but decided to try the SQL Server 2005 Standard Edition I got at the Italian Visual Studio 2005 Launch Event when I moved it to my laptop.

I was really impressed with the "Copy Database" feature in SQL Server 2005. It can copy the data using the standard SQL data management objects present in SQL Server 2000, but it can also attache a SQL Server 2000 database directly. I took my old MSDE DB offline, copied it to my laptop, attached the DB in the Microsoft SQL Server Management Studio and was up an running in less than a minute. It just worked.


Phase 2 (re-installing my server and moving everything back again) will take place tomorrow night.

Let me know if you find any problems.


A rough weekend ahead for my sites

The hard disks that started giving problems last year are giving up. Logging in on the server takes forever and posting fails sometimes so I have avoided posting the last few days.

I have already migrated mail services to my laptop and the blogs are next. The total downtime should not be more than a few minutes unless I find any unexpected compatability problems moving the blog from Win2k to Win2k3 and the DB from a MSDE to Microsoft SQL Server 2005...

Thursday, November 17, 2005


Nokia 6630 Bluetooth virus; pw9w3ozl.sis?

I was in a shopping center in Milano when I received a file called pw9w3ozl.sis via Bluetooth:

I did not, of course, install the application on my Nokia 6630 but I am dying to know what the heck it is. Google and Google News returned 0 hits so I guess it is either something "customized" for Italy or a virus/trojan uses a random file name while replicating.

I have the file in the inbox on the phone but I have been unable to transfer it to my PC for further analysis. Any suggestions on how I can get the file off the phone without installing it, or what it is???

Thursday, November 10, 2005


Italian Visual Studio 2005 launch event

There was a lot of good contents during the Visual Studio 2005 launch event. The presenters did a great job with the translated slides and demos from the US launch. As usual I loved the presentation by Fabio Santini which participated in the demo during the keynote.

The best part of the Visual Studio 2005 event? Meeting up with a lot of colleagues and ex colleagues; Andrea C, Andrea V, Luca M, Luca Q, Marco P, Marco T, Massimo L, Michele B, Samuele R, Fausto S, Rajesh V. 

Some "random" notes on Visual Studio

  • Microsoft claims there are more .NET developers than Java developers and a lot more SQL than Oracle databases. I work with both "worlds" and I am always amazed at how these numbers can be twisted/adopted depending on who sponsors the presentation
  • SQL Server is a lot more secure than Oracle. I have subscribed to the bugtraq mailing list for years and the number of security issues in Oracle the last few years are scary. Oracle had 20 security patches last year, 14 so far this year. SQL Server on the other hand had one security patch in 2004 and -zero- in 2005.
  • If you didn't know already: Visual Studio Express and SQL Express are FREE and downloadable via internet.
  • I was seriously impressed by the "data views" in Visual Studio 2005. I worked with PowerBuilder last millennium and just loved it's datawindows. Visual Studio 2005 is a step in the right direction but they still have a long way to go to catch up with the PowerBuilder datawindows which now can be integrated in Visual Studio

Some "random" notes on Server 2005

  • The statistics and DBCC functions have been refactored to be more consistent. Internal statistics are now made available via a large set of "Data Management Views" (sys.dm_*) and internal tables like sys.syscacheobjects. A lot of information that allows you to understand and tune your database like you never have before.
  • Lesson to self: query execution plans are cached by case SENSITIVE sql statements
  • The Execution times in seconds as measured on a reference machine in Microsoft labs. It is not the real CPU time on the hardware where you run the query.
  • Try this for fun
     Set statistics io on
     Set statistics profile on
     -- your query here
     Set statistics io off
     Set statistics profile off

  • Less on to self:  DB statistics are out of date if estimatedRows very different from Rows
  • Queries with "like '%abc%'" may work on 2005 due to improved statistics
  • Index on calculated columns
  • Asynch refresh of statistics, does not block execution

Some "random" ASP.NET and .NET 2.0 notes

The "loot"
The loot was impressive for a free conference:

  • Visual Studio 2005 Standard Edition
  • MSDN library
  • SQL Server 2005 Standard Edition
  • It's Showtime!. Loads of great presentations by some of the best minds in the industry
  • Visual Studio Team System (Virtual PC)
  • SQL Server 2005 Resource DVD
  • SQL Server 2005 (Virtual PC)
  • SQL Server 005 - Visual Studio 2005 Labs (Virtual PC)
  • Microsoft SQL Server 2005, Visual Studio 2005, BizTalk 2006: documentation by Microsoft and partners
  • Microsoft SQL Server 2005 and Visual Studio 2005 overview

(P.S. I am too busy with a major release to play around this weekend, but do not be surprised if there is some downtime this weekend as I upgrade my sites to .NET 2.0 and SQL Server 2005 :-)
(P.P.S It was too cold during most of the event to take of my jacket so I only manage to show of my blogger t-shirt during the last presentation

Edit: added two additional DVDs I found hidden in the bag :-)

Wednesday, November 9, 2005


Installing Visual Studio.NET 2005 over an old beta

My upgrade to Visual Studio.NET 2005 went without problems

Ah, the sweet smell of success :-)

I am very glad to report that the Visual Studio.NET 2005 beta uninstall tool worked like a charm. I was worried before starting as my laptop has had several Visual Studio .NET 2005 betas installed. Other versions of Visual Studio (6.0, 2003, C++ embedded etc) are also installed on the same machine for various projects. The uninstall tool is a provided on a "best effort" basis by the Setup Team
A fresh install is always better, but this setup will have to do until my next major software release is out the door later this month.

See you at the Visual Studio 2005 launch in Milano tomorrow? I should be pretty easy to identify with this t-shirt :-)

Tuesday, November 8, 2005


Sydney grows up and lifts the leg

Time flies and Sydney is growing up to be one big dog. For the first time this week he lifted the leg:

(sorry for the out of focus picture taken on a rainy morning).

I thought male dogs lifted the leg from the start but it turns out they only do it when the get older and wants to mark their territory. He is "calming down" a bit but the "downside" to growing up is that the walks take a lot longer as any smell is worth investigating. As all teenage boys he shows an increased interest for females. Sunday morning was the first time he "ran way". They gate stayed open since the previous night but he stayed inside until the female Labrador next door passed by on her -early- morning walk. What a way to wake up: the neighbor frantically pushing the doorbell.

Trust me; you would ring the bell when you see "the wolf" sneaking up on you as well:

(taken while picking chestnuts with my ladies earlier this autumn).

Friday, November 4, 2005


e-mail subscriptions to my blogs

I have recently added e-mail subscriptions to my blogs. It is a free service offered by FeedBlitz via FeedBurner.

Click the link at the top of each blog or the links below:

I have tested the service the last few days and it works like a charm. FeedBlitz will send you one mail each day with the new articles (images included) in all the feeds you have subscribed to. A "pro" plan is available on FeedBlitz if you want more frequent updates

Thursday, November 3, 2005


Windows Embedded Conference: Notes from Day 2

The second day of the Windows Embedded Conference was better than the first day.

Intel's presentations, in particular, were a lot more interesting. I am a software architect and I must admit that I have not followed the evolutions of the various CPUs as well as I did in the past so I learned a lot about the three families:

  • Xeon: high end/performance. Typically ~100 watts
  • Pentium 4: Mid range
  • Pentium m (+ celeron m): low power consumption: 5->15 watt

The Pentium M was designed from the ground up with low power consumption and performance in mind. Low power consumption and low heat emission is important not only in the embedded markets where having fanless systems is a benefit. They are also becoming more important in server farms where CPU heat is problem for blade servers.

Intel, as the other chip makers, have hit the 4Ghz CPU limit so they are working on several fronts to improve performance. The main news for 2006 is that all three processor families will become multi core (dual core initially). The current hyper threading technology simulates two processors in one execution core. During 2006 all the processors will get a real dual cores with two separate execution cores, separate L1 caches, registers etc. They will share the L2 cache and buss and live on the same piece of silicon. This has a more than 2X performance improvement, but most important of all, it gives more than 3.5X to 6X performance improvement /watt. The multi core scenario will continue to pack more cores on the chips during the next decade until we get real "micro" machines. Not only multiple cores but groups of cores.

They are also continuing to cram the transistors closer together. The best chips today use 90nm technology which will drop to 65nm next year. The road map is impressive as they already have 22nm prototypes and plan to drop to 8nm by 2017.

The Windows XP Embedded overview presentation was  held by Cesare de Siena  (Abacus ECC). A great presenter that cleared up a lot of my doubts about Windows XP Embedded.

Windows XP Embedded is a superset of Windows XP where you can choose which of the ~11.0000 parts/components of the OS you want to use. If your device doesn't have USB, why install the drivers for it as it takes precious resources? Any program written for XP works on XP Embedded as long as the correct parts have been installed. A Dependency Checker helps you with the task in case you try to remove too much.

The most interesting features of Windows XP Embedded is what is -not- in XP:

  • EWF: Enhanced Write Filter. You can configure your disk to be read-only so you can run it from a CD or write protected flash memory. It supports multiple volumes so the read-only OS image can be on a write protected volume while user data is saved on another volume.
  • Device Driver Rollback: If a new driver fails you can roll back to the previous version. The impressive thing is that it actually works (according to the presenter :-)
  • Remote Boot allows disk less installations as you can have the OS image on a remote server
  • Message Redirection: a -must have- feature for headless installation. I don't know many times I have seen error messages on public terminals with message like "you are running low on disk space". The message redirection allows you to provide configurable answers to messages like that or redirect them to an external system.
  • HORM. Hibernate Once, Resume Many must be the coolest feature of them all. Resume is no new feature as it also works on XP, but couple with EWF you can have a read-only hibernated state. The device can resume from a known stable hibernated state from a flash disk in an instant. No matter what "damages" the user does to the system, it will reload from the same read-only image after a hibernation or a reset,

At the end of the presentation I "saw the light" and saw other uses for it than the typical kiosk application. XP Embedded would be perfect for locked down PCs for kids and students: the operating system can be write protected and the computer turns on in an instant with HORM. No way you can mess up the machine with the control panel if it is not installed...

It has no online activation and costs ~30% less than the normal Windows XP so it's the perfect solution if you want to tinker a bit

Overall judgment of the conference? Good.
I learned a lot of new things today and the sessions were definitely worth my time. It is a shame that you either follow the presentations or attend the labs. Less "marketing" issues the first day and a chance to get hands-on experience in the labs would have given a “great“ vote.

One final word: ecosystem
I don't know how many times I have heard the word ecosystem these days, but it is as bad as "empowerment" was last year...

Wednesday, November 2, 2005


Windows Embedded Conference: Notes from Day 1

The first thing that struck me when the Windows Embedded conference started; embedded developers are different from .NET developers. No long haired, enthusiastic,C# developers here. The average age is easily 20 years higher and these engineers are a quiet and reserved bunch...

The were two hands on sessions in the afternoon but I followed the presentations. I will post the link to the slides when they are put on-line later this week. Below are some of my notes/impressions from the meetings.

The Windows Embedded family is larger than I expected. I knew of Windows CE.NET and Windows XP Embedded but I didn't know there were many flavors of Windows 2003 Server Embedded as well as a new "point of service" system (WEPos) targeted at point of sales systems like kiosks.

Some Windows CE.NET notes:

  • It is a Hard Real Time OS since version 4.2.

  • Supports many different processor architectures and is, of course, not binary compatible with Windows

  • A subset of the Win32 APIs have been written to the same specifications. This means that there are variations but things are a lot better than the first Windows CE versions.

  • The Platform Builder comes with source code for a several potions of Windows CE.NET which helps when writing drivers for your own hardware. More of the source code is available for free after signing the appropriate Microsoft documents.

  • Windows CE.NET is cheaper than I expected. The run time license for the core is ~$4.50 per client (~$3 for high volume). The cost goes up to ~$16 for the professional edition that includes Internet Explorer and the Media Player

  • You can lock down the Windows CE file system and to control which application can be launched.

The best presentation of the day was Windows CE 5.0 Technical Overview by Egidio Gioia (Arrow Silverstar). A lot of useful information by someone who knows the subject extremely well. He covered technical issues and hard learned lessons while skipping the marketing fluff. His monthly boot camps should be very interesting.

The Intel presentations were less useful for me as I work on software but it is always good to know what goes on below the hood. The PXA270 processor used in the latest Pocket PC has impressive power savings when it is in deep sleep mode.

The presentations tomorrow will focus on Windows XP Embedded.

Overall judgement? OKish.
Too much high level “marketing“ issues for my taste with the exception of Egidio's presentation.

Tuesday, November 1, 2005


Web Service to send any message to any phone number in US/Canada

The PhoneNotify web service by cdyne is as useful as it is scary, since you can specify any caller id you want:

This Method will call any phone number in the US/Canada and read the TextToSay to that phone number.
Set VoiceID equal to 0 for TTS Diane to speak the Text. For a list of Voices with their ID look at getVoices. PhoneNumberToDial and CallerID must be filled in (They can be in any format as long as there is 10 digits).
A reminder about abuse: Threats and illegal activity can be shared with the authorities.
Use a LicenseKey of 0 for testing.

I do not have a phone in the US or Canada so I have not been able to test if actually works. Any volunteer testers?

Via API Blog


Blog properly formatted code from Visual Studio 2005

Jeff Atwood has created a great macro for Visual Studio 2005 that allows you to cut and paste code like it should be done. It even removes unnecessary white space! The Visual Studio plugin to copy source code as html  has more features but it requires you to install the plugin.

Get the latest versions of both alternatives and give them a try, especially if you post a lot of code:

Via Coding Horror

Thursday, October 27, 2005


Windows Embedded conference November 2-3

I am going to the Windows Embedded conference next week (November 2-3) in Milano

See you there?


How to replace multiple strings in XSL

It has been a while since I have done some serious xsl coding so I had some fun today when I was asked how to replace multiple strings in XSL. This is a piece of cake if you use a Microsoft XML parser (MSXML or .NET version) as you can call JavaScript using the proprietary msxml:script tag in xsl. Just write a simple function like this:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet xmlns:xsl="" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:egilh="" version="1.0">

 <msxsl:script language="JScript" implements-prefix="egilh">

 function replaceString(source, find, replaceWith) {

  var result = source;

  while (result.indexOf(find) >= 0){

   result = result.replace(find, replaceWith);


  return result;




 <xsl:template match="/">

   Test: <xsl:value-of select="egilh:replaceString('abcd', 'b', ' CoolOrWhat ')"/>





Xpath 2.0 solves the problem as you use the replace function but in this case they were using a Java XSL parser...

I have tried to implement a generic and configurable solution. It uses an external XML file that contains the search and replace strings. You only have to include the replace.xsl in your stylesheet and call the template to replace as many strings as you want.

Step 1: Include the xsl
Add the following line after the <xsl:stylesheet> declaration but before the first <xsl:template>:

    <xsl:include href="replace.xsl"/>

Note: You must put the replace.xsl file in the same directory as your stylesheet or modify the href

Step 2: call the "replace  routine"
Call the replace routine which is implemented as a template. You have to pass it the following arguments:

  • the text to search in

  • the XML nodes with find/replace elements

<!-- Replace strings found in replace.xml --> 
<xsl:call-template name="replaceStrings">
  <xsl:with-param name="inputText" select="."/>
  <xsl:with-param name="search" select="document('replace.xml')/SearchAndReplace/search"/>

The example above workes on the current node (.). It gets the list of items to search and replace from the external file 'replace.xml'. You must put the replace.xml file in the same directory as your stylesheet or modify the path.

Step 3: configure the text to search and replace
The replace.xml file defines what to search for and the text to replace it with. It has the following format




  <replace>Did you say 1?</replace> 



How it works
Replace.xsl uses two recursive templates to do its work:

  • replaceStrings (inputText, search):

    • Loops on the search nodes. It calls the replaceString() for the first element in the list, then it calls itself with the remaining elements in the list

  • replaceString(sourceText, findText, replaceText):

    • Loops on itself as long as findText is found in the sourceText.

    • It replaces the first occurrence it finds using substring, then it calls itself again. 

    • NB!: You can get never ending loops that bomb with a out of stack space errors if the findText is contained in the replaceText. Replacing "a" with "abc" for example will forever replace the first element with "abc". It is possible to avoid this by passing an offset to replaceString.


<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="" xmlns:fo="">  


      <xsl:template name="replaceStrings">

        <xsl:param name="inputText" />

        <xsl:param name="search" />


      <!-- Debug -->


      [inputText: <xsl:value-of select="$inputText"/>] 

      [find: <xsl:value-of select="$search[1]/find"/>] 

      [replace: <xsl:value-of select="$search[1]/replace"/>]  


        <!-- Replace the FIRST string in the replace list -->

        <xsl:variable name="replaced_text">

            <xsl:call-template name="replaceString">

              <xsl:with-param name="sourceText" select="$inputText" />

              <xsl:with-param name="findText" select="$search[1]/find" />

              <xsl:with-param name="replaceText" select="$search[1]/replace" />




            <!-- If there is (at least) one more element -->

            <xsl:when test="$search[2]">

              <!-- Call ourself with the remaining list of elements

                    (removing the first one -->

              <xsl:call-template name="replaceStrings">

                  <xsl:with-param name="inputText" select="$replaced_text" />

                  <xsl:with-param name="search" select="$search[position() > 1]" />





              <xsl:value-of select="$replaced_text" />






      <xsl:template name="replaceString">

        <xsl:param name="sourceText"/>

        <xsl:param name="findText"/>

        <xsl:param name="replaceText"/>

        <!-- Debug statements -->


          [sourceText: <xsl:value-of select="$sourceText"/>]

            [findText: <xsl:value-of select="$findText"/>]

            [replaceText: <xsl:value-of select="$replaceText"/>]



            <!-- If the output contains the text we are looking for -->

            <xsl:when test="contains($sourceText,$findText)"> 

              <!-- Replace using substring before + new text + substring after -->

              <xsl:value-of select="concat(substring-before($sourceText,$findText),$replaceText)"/>

              <!-- Apply template again to replace the next occurence -->

              <xsl:call-template name="replaceString">

                  <xsl:with-param name="sourceText" select="substring-after($sourceText,$findText)"/>

                  <xsl:with-param name="findText" select="$findText"/>

                  <xsl:with-param name="replaceText" select="$replaceText"/>




              <xsl:value-of select="$sourceText"/>





Example Replace.xml




  <replace>Did you say 1?</replace> 







I based my implementation on the hints I found in the following articles:

Wednesday, October 26, 2005


How to track down performance problems in COM+ applications

Someone asked me yesterday if the COM+ Call Time Tracker can be used dig deeper into the component to see which function is causing the high call times. It is an interesting subject, so I am posting the reply on the blog.

The answer is no, COM+ only gives call information on an object level. It does not give information about internal information like function call times. This means that the COM+ objects must be split into smaller COM+ objects you want to track down the problem with COM+ call time tracking. It is an ugly solution, and only works on a "macro" level as it is not feasible to make all the functions separate COM+ objects. There are better alternatives which I cover below.

First of all; keep in mind that call time is not the same a CPU time. The call time shows how long COM+ has been waiting for a the object to return. The object may be busy:

  • calculating something (using a lot of CPU),

  • writing something to disk

  • waiting for an external resource like a Web Service or a query to a DB

  • waiting for a lock on a shared resource

- Task Manager -
This is the first think I have a look at if I have problems with high call times in COM+. It is already installed on the machine and it gives an idea what is going on.

Things to check in the "Performance Tab":

  • CPU Usage. It should be lower than 50% on average, never over 75% for long periods of time

  • Commit Charge must be lower than Physical Memory, otherwise the machine does not have enough memory and will swap. Everything slows down when the machine swaps so you will get high call times in all components..

Then I look at the process running the COM+ Application. The COM+ Call Time Tracker already gives you the process ID in /applications/application/processID but you can also get it from Component Services. I usually check the following information in Task Manger for the Process ID; CPU, Mem Usage, Peak Mem Usage, VM Size, Handles

Some quick rules of thumb:

  • High CPU usage is pretty obvious. Improve your code or get more/faster CPUs

  • VM Size > Mem Usage means a memory leak. The machine starts swapping out memory and everything slows down

  • Handles:  Should be stable. An every increasing number means a handle leak in the component (usually references to external objects/files that are not closed)

  • If Peak Mem Usage is a lot larger than "Mem Usage", there are periods when the component uses a lot of memory

- Performance Monitor -
Performance Monitor (perfmon.exe) is a very powerful tool if you know how to interpret the results. It can be used to monitor most resources on the machine, often on a process by process basis. It allows you to find the overall bottle neck: cpu, disk, memory, network, web worker processes etc.

- Process Explorer -
The free Process Explorer by Sysinternals is a fantastic tool. Consider it Task Manager on steroids enhanced with Performance Monitor data. The latest version tells you everything you ever wanted to know about the processes running on your PC; how many threads they have, how much CPU each thread is using, which DLLs it is using etc.

One thing to check for .NET applications: The “% time in GC” counter below shows how much of the applications CPU time is spent on garbage collection. It must be less than 4-5% on average. Higher values means .NET spends a lot of time garbage collecting objects that have not been closed or disposed properly. I have seen cases of >70% cpu usage for garbage collection due to bugs in the code.


- Logging -
A good log is crucial when troubleshooting any problem, including performance. I usually use log4net but any other logging framework that works in a multi threaded environment  is OK. Use the different log levels to control how much is logged as detailed logs will slow the system. You can use a trace/info level to log function entry/exit points, so you can see which function grabs the time, but log input/ouput and more verbose data at the more detailed debug log level.

- Code Profiler -
Code Profilers monitor the execution of a process and tells you afterwards how many times the different functions were called, how long it took etc. Code Profilers usually run on a development or test PC so you have to simulate the calls you make in a production environment using a dedicated tester.

There are several professional tools on the market like ANTS Profiler by Red Gate and DevPartner Studio by Compuware

So far I have never had to use one as I have managed to track down bugs with a combination of performance counters, logs and code reviews.

Tuesday, October 25, 2005


KPL: Kids Programming Language

The free Kids Programming Language development environment comes with a many fun programs, mostly games, that the kids can play around with and modify as they wish.  I learned programming by playing around with the examples that came with Turbo Pascal and I really believe in Learning by doing.  The working games with neat graphics and sounds is fun to play around with and tweak for kids of all ages.

Kid’s Programming Language (KPL) was designed and developed based on the principle that programming is fun - and that learning is best achieved when the learning material is fun, intuitive and interactive. KPL is composed of:

  • a readable and modular programming language

  • a kid-usable but functionally complete integrated development environment

  • a growing collection of entertaining and educational sample programs

  • an experience that enables and encourages kids' imagination, curiosity and creativity

We developed Kid’s Programming Language (KPL) as a way to teach our own kids how fun it is to write code, and KPL turned out so well that we are working hard to figure out how to also share it with as many other kids as we can. 

The language itself borrows a lot of the syntax from VB.NET with some elements from C#. The GUI looks like a simplified version of Visual Studio.NET (which makes it simpler for dad to give support :-)

Microsoft will promote the new programming language by Morrison Schwartz  to replace basic as the first language students learn.

Friday, October 21, 2005


Windows Bluetooth scanner

The BlueScanner, by Network Chemistry, is a Bluetooth discovery tool for Windows. It finds all Bluetooth devices in range and the the services they offer. I had some problems on my Compaq nx7010 but you may have better luck on your PC

Thursday, October 20, 2005


DVD Jon lands a job for MP3Tunes

Fellow countryman Jon Lech Johansen (aka "DVD Jon")  recently started working with Michael  Robertson of, SIPphone and Lindows Linspire fame.

Wall Street Journal ran a front-page story about Jon Lech relocating so he got loads of new job offers, but he seems happy where he is:

 I [Michale Robertson] talked to him over lunch today and asked if he wanted to work at those other companies. "Not really," he replied in a typical minimalist Scandinavian-style reply, forcing me to ask why not. "I want to work on open systems, which is why I came to you."

The best of luck to Jon in his new adventure!

Via [Michael's Minute]