S h o r t S t o r i e s

// Tales from software development

Archive for December 2009

Death of the PDA

leave a comment »

Twice in the past month, or so, I’ve become aware of a technological change in the landscape by trying to buy something that has become scarce because its time has passed.

The first was a few weeks ago when I had a leak in the plumbing in my house and my phone call logger got soaked and died. The logger was pretty useful because it logged all incoming calls with the date and time and also ‘announced’ recognised callers. If the phone number provided by Caller ID matched a known phone number it replayed a voice annotation which you’d typically set up as the name of the caller. So, even without checking the Caller ID display on the log or the phone itself you’d know if it was a friend or family member calling.

I went shopping for a new Caller ID log and discovered that they’ve almost disappeared. Because most phones now incorporate a Caller ID display the sales of separate Caller ID displays and loggers has dropped off to the point where no one is bothering to manufacture or market them.

Next, last week I discovered that the PDA is in a similar terminal decline. I have a couple of PDAs that I regularly use and was thinking about buying a newer model to replace one of them. While browsing a couple of the more popular online retailers’ web sites it quickly became apparent that the dedicated PDA is all but dead.

As an example: one retailer lists 37 products under ‘PDA’ of which 36 are actually smartphones and only one, the HP iPAQ 214, is a dedicated PDA.

When I bought my last PDA, about five years ago, everyone was talking about the convergence of PDAs, phones, and GPS. Like many people, I had at least one of each back then and spent a lot of time trying to connect them with each other. Convergence was a distant nirvana but it seems that we got there sooner than many of us anticipated.

What surprised me in both of these examples though was the fact that the passing of these devices has gone largely unnoticed. While new types of devices are always heralded by the the manufacturers and retailers, the old ones just slowly and quietly fade away and die.

Written by Sea Monkey

December 30, 2009 at 8:00 am

Posted in Comment

Tagged with

WiX: Registering a .NET COM Interop assembly

leave a comment »

I needed to register a .NET COM Interop assembly as part of a deployment but the WiX documentation doesn’t give explicit details on how to do this. Searching for an answer shows that a few people are using custom actions to invoke RegAsm at install time. This approach is wrong for several reasons but let’s stick with the idea that the Windows Installer won’t know it needs to unregister the assembly on an uninstall as being one of the more significant.

The solution is fairly simple: generate the TLB for the interop assembly using RegAsm and then run Heat against the assembly and the TLB:

RegAsm.exe InteropAssembly.dll /tlb
Heat.exe file InteropAssembly.dll /out asm_fragment.wxs
Heat.exe file InteropAssembly.tlb /out tlb_fragment.wxs

Copy the two WiX fragments in the .wxs files to your WiX source and edit them as required.

Written by Sea Monkey

December 24, 2009 at 8:00 am

Posted in Deployment

Tagged with

Logging: The good and the bad.

leave a comment »

The application I’ve been working on for the past few months is now undergoing integration testing at the client’s site. It’s an interface between a strategic data store that we’ll call CLIDAS and our application, Vitality.

There’s some fairly complex processing in the interface and it was obvious from the start of the project that it would have to have comprehensive and detailed logging in order to confirm that it was doing what it should and to understand why it wasn’t if that was the case.

In testing the interface has proved to be robust and reliable. Unfortunately, it’s highlighted a whole load of problems in the CLIDAS system which frequently throws exceptions when the interface is requesting data.

The interface’s log files clearly show what it was doing, what the call to CLIDAS was, the arguments used, the execption that was thrown by CLIDAS, the  exception stack trace, and, of course, the exact date and time the error occurred.

Last week we noticed a problem where a particular call to CLIDAS always resulted in it throwing an exception. So, we emailed the client with all the details: date and time, type of exception, exception message, what the interface was doing at the time, what the call to CLIDAS was, and the arguments used.

The CLIDAS system is maintained and developed by a third party company under a multi-million pound contract. I guess how much money you throw at development doesn’t always mean a good implementation because the guys from the third-party emailed the client back with this:

“We can’t see any problem. Can the guys at Vitality tell us any more about the CLIDAS error ?”

Great! So, the CLIDAS system apparently isn’t logging errors and having given these guys every possible piece of information about the exception from a caller’s perspective, they’re still asking for more. There’s a hint of desperation in their email that implies that what they’re really asking is, can we tell them what’s gone wrong with their application ?!

Logging is a perfect example of how a little bit of time and effort during development pays for itself many times over downstream.

Written by Sea Monkey

December 22, 2009 at 8:00 am

Posted in Development

Tagged with

Amazon recommends…

leave a comment »

Just received this email from Amazon:

Dear Amazon.com Customer,
As someone who has purchased or rated Platinum and Palladium Printing by Dick Arentz, you might like to know that Preparation of Thin Film Pd Membranes for H2 Separation from Synthesis Gas and Detailed Design of a Permeability Testing Unit (Chemical Engineering Methods and Technology) will be released on January 1, 2010.

What ? So, because I bought a book on photography Amazon is recommending a chemical engineering treatise on hydrogen separation ? You’d have thought that the software that creates Amazon’s recommendations was more sophisticated than keyword matching but obviously not. 

 

Written by Sea Monkey

December 19, 2009 at 12:00 pm

Posted in Comment

Tagged with

The limits of ServicesPipeTimeout and ServiceBase.RequestAdditionalTime

with 7 comments

The project that I’m currently working on uses a Windows Service. We deployed the project to the customer’s acceptance testing environment earlier this week and the service failed to start. Each attempt just resulted in a “Error 1053: The service failed to start in a timely fashion” message.

There’s some code in the executable’s entry point that validates the service’s configuration data and, as part of this, runs a query against a database. In the development and test environments this query completes in around 5-6 seconds but in the production environment it takes around 50 seconds. The Service Control Manager (SCM) expects a service to start in 30 seconds, or less, and aborts the start if it takes longer.

If you search the internet for similar problems and possible solutions you’ll see that there’s a registry hack to extend the time the SCM allows for a service to start. You can set the ServicesPipeTimeout DWORD value in HKLM\System\CurrentControlSet\Control\ to the value in milliseconds that you want the SCM to use as a timeout. Except… It didn’t work for me.

There are two actions that the SCM takes to start a service. First it loads the executable and calls its main entry point. In a .NET assembly this code will create an instance of a class derived from ServiceBase and call the static Run method to perform the service initialization and then return control to the SCM. The SCM then calls the service’s Start code which is handled in the derived class’s overridden OnStart method.

It appears that the ServicesPipeTimeout value doesn’t have any bearing on how long the SCM will wait when it calls the service executable’s main entry point and, of course, this is where my validation code was. I haven’t confirmed this yet but I’m guessing that the ServicesPipeTimeout value only affects how long the SCM waits when it”s called the Start method.

I moved the start up validation code from the main entry point into the OnStart method. At this point increasing the value of ServicesPipeTimeout would probably have resolved the problem but it would also apply to all the services on the machine and I wondered if there was an alternative that would only affect my service. A quick browse of the methods exposed by the ServiceBase class revealed the promisingly named RequestAdditionalTime method.

I wrote a test service that waits for configurable amounts of time in the entrypoint code, the OnStart, and the OnStop event handlers. I found that RequestAdditionalTime does indeed cause the SCM to wait longer than the default timeout period specified by ServicesTimeout but only up to a point.

The MSDN documentation doesn’t mention this but it appears that the value specified in RequestAdditionalTime is not actually ‘additional’ time. Instead, it replaces the value in ServicesPipeTimeout. Worse still, any value greater than two minutes (120000 milliseconds) is ignored, i.e. capped at two minutes.

Two minutes is still a lot more useful than 30 seconds but there’s no excuse for Microsoft not documenting this limitation. Even the BCL Team’s blog entry on the subject doesn’t mention it.

Written by Sea Monkey

December 18, 2009 at 10:00 am

Posted in Development

Tagged with

MySQL query fails with "Query execution was interrupted"

with 4 comments

The project I’m currently working on has a Windows Service that loads some static data from a MySQL database when it starts. The query that returns the data has always executed slowly in my development environment and occassionally the query has reached the default timeout value of 30 seconds before completing. I hadn’t bothered to add some code override the default value as in the production environment the query executes fairly quickly and is never in danger of timing out.

When the query times out the service fails to start. Usually, just starting the service a second time will be successful although I’d sometimes get a second timeout with an appropriate timeout error message in the exception, one further attempt to start the service would succeed.

Not today though… And, the error message in the execption looked much more serious: “Query execution was interrupted”. After attempting to start the service about five or six times it was clear that it wasn’t going to succeed this time.

It took a few minutes to realise that this is probably a bug in MySQL. The error always occurred exactly 30 seconds after the call to MySQL to execute the query. So, this almost certainly is a timeout error but the wrong message is being passed back in the exception.

What seems to be happening is that the query times out and MySQL cancels it. The correct error message is passed back to indicate what happened. When the same query is executed again, MySQL is killing the query when the timeout is reached but is appears get confused about why the query is being cancelled. Possibly, because the same query was previously killed, it’s deciding that someone has requested the cancellation of the query execution without checking to see that it’s actually MySQL’s timeout handler that previously cancelled the query and is doing so this time too.

Setting an explicit, and longer, timeout value in the Command object’s CommandTimeout property fixed the problem.

Written by Sea Monkey

December 4, 2009 at 1:00 pm

Posted in Debugging, Development

Tagged with ,

Reading values in an XML configuration file from a batch file.

leave a comment »

The last couple of projects that I’ve worked on have included a couple of batch files as part of the deployment. These use some values such as file paths and database connection strings that are specific to the deployment environment and, ideally, should be configured by the installer. Although the WiX Util namespace includes a couple of tasks to modify an XML file it doesn’t offer any means to modify a text file such as a batch file.

So, I wondered, could I put the configurable values in an XML file and access them from the batch files ? It seemed unlikely but it’s actually surprisingly easy. It’s not pretty though…

In the following example the value to be retrieved is the text between a <connectionString> element and its matching end element in an XML file called config.xml:

FOR /f "tokens=2 delims=><  " %%a IN ('TYPE config.xml ^| FIND "<connectionString>"') DO SET CONNECTION_STRING=%%a

 
What isn’t obvious in the code above is that the delims argument is set to four characters – the greater than sign, less than sign, space, and tab.

The value is placed in an environment variable called CONNECTION_STRING.

It really is as simple as that!

This can be made a lot more sophisticated by using some of the features that Microsoft has added to batch processing over the past few iterations of Windows. For instance, put the code after a label and then call the label passing in a set of arguments such as the name of the file, the name of the value to be read, and the name of the environment variable to place the value in:

:GET_CONFIG_VALUE
REM Must be called using this syntax:
REM CALL :GET_CONFIG_VALUE cmd-filename config-filename config-value-name variable-name
REM where
REM   cmd-filename is the name of this file, e.g. use %~f0
REM   config-filename is the name of the XML config file
REM   config-value-name is the XML element name of the value in the config file
REM   variable-name is the name of the environment variable that should be set to the value found in the config file
SET GCV_CONFIG_FILE=%2
SET GCV_VALUE_NAME=%3
SET GCV_VARIABLE_NAME=%4
REM Note that the delims arguments used below include the tab and space characters.
FOR /f "tokens=2 delims=><  " %%a IN ('TYPE %GCV_CONFIG_FILE% ^| FIND "<%GCV_VALUE_NAME%>"') DO SET %GCV_VARIABLE_NAME%=%%a
GOTO :EOF

 
It’d be useful to have a generic routine for missing values too:

:MISSING_CONFIG_VALUE
ECHO ERROR: No value was found in the '%GCV_CONFIG_FILE%' file for '%GCV_VALUE_NAME%'.
GOTO EXIT

 
This code can now be called from the body of the batch file like this:

SETLOCAL
REM Get the configuration values from the config file:
SET CONFIG_FILE=%~f0.config
CALL :GET_CONFIG_VALUE "%~f0" "%CONFIG_FILE%" connectionString CONNECTION_STRING
IF "%CONNECTION_STRING%"=="" GOTO MISSING_CONFIG_VALUE
CALL :GET_CONFIG_VALUE "%~f0" "%CONFIG_FILE%" connectionTimeout CONNECTION_TIMEOUT
IF "%CONNECTION_TIMEOUT%"=="" GOTO MISSING_CONFIG_VALUE
REM Do some stuff here...
ENDLOCAL
GOTO :EOF

 
Most of this is obvious but it might be worth pointing out that %~f0 evaluates as the filename of the batch file that’s executing.

Written by Sea Monkey

December 2, 2009 at 10:00 am

Posted in Deployment, Development

Tagged with ,