Eclipse 3.1 M2

The Eclipse team seem to have stopped announcing Milestone releases on the front page, so it’s a bit tricky to know when a new one is released.

So it may be old news, but Eclipse 3.1 M2 has been released.

It contains some nice new features.

The Milestone builds are extremely stable, so there should be no problems using it.

Head First Servlets & JSP

Today I bought myself Head First Servlets & JSP.

While I have absolutely no intention in passing any Java related exam or even do anything JSP-ish in the near future (see my reasons here, here and here), I had to have the book.

Why?

For one thing: While I have my problems with Java, I’m still very interested in it and the technologies around it. This is the reason, why I’ve already read one or the other book about JSP. The scond reason: The “Head First” series is absolutely the best way of how a tech book can be written. It’s a pleasure to read them.

They are that good, that it’s even worth reading them even when you don’t really need to learn what’s in them. It’s just fun to read it. Try it yourself!

A look at Windows Installer

Before I begin, let me put this disclaimer: I’m biased, so this is maybe not objective, but it’s something I wanted to say. And who knows: Maybe you even think the same.

As you may know, Microsoft would really like to see all software using Windows Installer for its deployment needs. Windows Installer is a complex piece of technology, evaluating some kind of database that’s stored in those .MSI-Files.

Windows 2000 Server and later, namely with its Active Directory, provides the system Administrator with the ability to automatically install and update MSI based applications on the client computers, which definitely is a good thing. Additionally, MSI should provide end users with clean uninstalls, automatical repair and the solutions to COMmon [;-)] problems. Sound’s like a good thing, doesn’t it?

It would – if there was not quite a heap of problems associated with Windows Installer

  • First, the thing is intransparent and messy.
  • I have migrated my user profile to another machine, where not all the software I had on the previous machine has been installed. So the control panel was full of software that was not installed on the machine. Hitting “Remove” caused MSI to request the original installation MSI file (why the heck?) and with me failing to provide it (why should I redownload something just to remove traces of it from my machine if I don’t want it in the first place) and hitting “Cancel” removed the entry, but it reappeared when reloading the control panel applet. Cleaning the registry did help, but tell me of an end user capable of doing that.
  • Whenever I drop an URL from my Browser to the desktop, MSI pops up and wants to repair some software I’ve already removed. For this it asks me to provide the path to the original media. Why?
  • Creating Update-Packages is a pain in the ass: You have three possibiliteis:
    1. Create a “full update” which will first uninstall the existing version. That way you have to go great lengths to preserve the user’s data because it’s not that easy detecting whether the uninstall happens because of the upgrade or just is a normal uninstall. This, I want to add, is the recommended way of updating an application deployed by MSI
    2. Create some update-package. This often needs quite a bit of hacking to the MSI-File, leading to problems like MSI-Dialogs popping up asking for some files.
    3. Create a patch-File (.MSP). In MSI pre 3.0 this is a pain in the ass if you want to prevent the user from having the original MSI-File ready. Too bad, MSI 3.0 runs only on Win2k and later

Windows Installer is very tightly integrated into the system. Even small problems here and there (non-clean uninstallation or whatever) can cause major problems that are not really fixable. This is not what I call an end-user friendly technology.

And it does not end there: Have you ever tried engineering a MSI-File? You may begin by reading the SDK documentation I linked to above, but you will soon be overwhelmed – the beast is incredibly complex. But with complexity does not come feature-richness. For example, it’s impossible to install the .NET framework from an MSI based installation as only one of them may be running at the same time.

Because of this and many other problems, it’s the general oppinion to create a self extracting .EXE installing the prerequisities and then passing the control over to the MSI-File which still isn’t capable enough to do many things, setup authors today are used to do.

Big tool Vendors like WISE Solutions or InstallShield go great lengths to hide the comlexity of MSI and to add features not there in the basic version, while sometimes breaking validity of the generated packages or even the one big advantage of MSI’s: Transactional functionality. Thus, taking away the last benefits, MSI may have.

Conventional Installer Tools are availbable for free (InnoSetup, NSIS) and have a much more pleasant user experience: No silly questions for source packages, no confusing breakage and more.

Of course: Some things those conventional tools will never be able to provide:

  • Advertized Features (and Shortcuts)
  • Automatical Self-Repair
  • Advertized Installations (which allow restricted users to install certain packages)

    But to be honest: Which one of those features provides real value to the end user? I know many people that have installed MS Office, for example and no one of them – absolutely no one has instructed setup to install features on demand – nobody wants to insert the office CD at random events.

    In contrast: Everyone I know simply hates those Windows Installer dialogs popping up, requesting the source image. Lukas for example is unable to remove PGP Deskop becuase the uninstaller requires the installer package which can’t be provided as it’s packaged in a self extracting .EXE using a proprietary format. Simply reinstalling from this .EXE isn’t possible either because the extracted MSI detects the existing installation and want’s to uninstall but still does not recognize the extracted original MSI. Bad luck.

    So in the end MSI looks to me like an administrators thing, but not like a tool making the live easier for the end user. With tools like InnoSetup, I can create an user expirience that even non-tech-savy users understand and that even has no further problems popping up later. Granted: More advanced tasks are better integrated into MSI (Installations per User/Per System), but can be done with the conventional tools, if some thought is put into the installation.

    For now, I will definitely stay with InnoSetup and keep my supporting work focused on real application issues, not wierd MSI problems. For Administrators, installing PopScan for their users, we provide a detailed documentation describing, which file goes where and what the installer does, thus providing the administrator with the means of either create an MSI (which can be done automatically these days. The result is not optimized, but it does it’s job. Combined with our documentation, this can be a real alternative) or use other technologies to deploy the software.

Working with subversion

I’m currently making first steps using Subversion and it’s going quite well. It took some time to get the $Id$ expansion to work though, but this article helped me in the end.

The next thing I’m going to do is trying to migrate a simple project (no braches, no tags) from CVS to subversion. I know there are some tools out there which promise being able to do that for you, so I hope it’ll work.

The final step would be to migrate over PopScan, which has gotten quite complex these days: About 5 branches, countless tags and three years worth of history data. If that too goes well, it’s “welcome subversion” for me. If not, I think, I’ll postphone the migration until the tools get better. I absolutely don’t want to have my code in different source management systems.

I’ll keep you posted.

PHP 5

As you surely know, PHP 5 has been released. Actually, it’s already 5.0.1.

What you also may know is that Gentoo’s dev-php/mod_php package was promoted from -x86 to ~x86. This means from broken to unstable in Gentoo-terms.

This means that I can now make some tests with PHP5 which I already began doing: I’ve upgraded PHP on our developement server to 5.0.1 and it’s working quite well so far. The only problem I’ve come across is this stupid code in a osCommerce installation:

class something{
  function something{
    // do something
   $this = null;
  }
}

New or old object model in PHP: This is just something you don’t do. Not in PHP, and certainly not in any other language. You should not assign anything to this, self or even Me (or whatever the implicit pointer to your own object is called in your language).

Copying with MOVE? Moving with copy?

Today I came across the situation where I had to copy – using delphi – some chunck of memory from one place to another. I nevery did that before (using OOP techniques gets you around that most of the time – at least in Delphi), so I had no idea how to do it. What I knew is that in C, I’d do that with memcpy. As a convinced fan of Pascals intuitive API notation, I looked in the help for MemCopy or CopyMem. Nothing (which is strange, considering things like AllocMem actually exist).

Some googling around turned out the name of the function: it’s

procedure Move(const Source; var Dest; Count: Integer);

Move? That can’t be. Can it? I want to copy, not to move. A quick glance at the help file revealed that it’s the truth: Move actually copies…

Move copies Count bytes from Source to Dest. No range checking is performed. Move compensates for overlaps between the source and destination blocks.

Descriptive procedure names? Usually, yes. But this can only be described as way beyond the optimum ;-)

Oh… on another note: What do you think, Copy does? Copying memory? No way:

function Copy(S; Index, Count: Integer): string;

function Copy(S; Index, Count: Integer): array;

S is an expression of a string or dynamic-array type. Index and Count are integer-type expressions. Copy returns a substring or subarray containing Count characters or elements starting at S[Index]. The substring or subarray is a unique copy (that is, it does not share memory with S, although if the elements of the array are pointers or objects, these are not copied as well.)

If Index is larger than the length of S, Copy returns an empty string or array.

If Count specifies more characters or array elements than are available, only the characters or elements from S[Index] to the end of S are returned.

Yeah!. Right.

Oh and on second thought: The move-thing may have its roots in the assembler language, where MOV actually copies the data too – at least I think so. But anyway: If even C got it right, why has my beloved Pascal to fail in such an easy case?

Responding to search-strings (II)

While looking through the logfile analysis of gnegg.ch I saw that someone came to this site searching with

set ie proxy delphi

so I deceided that it’s time for anther episode of “Responding to search-strings” (the other being here). This time it’s about setting the IE’s proxy server from a delphi application.

When you do it manually, you access the proxy server settings from Tools / Internet Options / Connections in Internet Explorer. Whatever you change there, is used not only by IE, but by every application on your system using the WinInet API function InternetOpen with the flag INTERNET_OPEN_TYPE_PRECONFIG set. Additionally, many applications use the WinInet-API to get the Proxy Server settings and then use their own routines to actually connect to the server via the proxy they got before

So, if you want to change the Internet Explorer Proxy settings, you actually change it for the bigger part of the wohle system

When you go to Tools / Internet Options / Connections, you will immediately see that setting the proxy is going to be quite a task: You don’t just set one proxy server, you actually set one for LAN-Connections and one for each dialup connection that is installed on your system. Finally the proxy being used depends on the state of the radio buttons you see in the middle of the dialog because they define whether IE should even bother connecting to the LAN or just call one of the connections defined.

But it gets even more complicated: The proxy settings provided changed for each version of Internet Explorer. As always, it was an evolutionary process getting more complex in every iteration, so you will have to cope with that too.

But now to the details: While the settings are stored in the Registry, this is not the recommended way for changing them. Microsoft has created some API functions specifically for that, so you should use them as this is the only way guaranteed to be portable even for future versions of Windows.

The problem: The API is very painful to use – even more so because it is somewhat different for each version of IE (getting more complex along the proxy feature itself). Oh, and please don’t ask me how to get the version of the installed IE – that I do not know.

All is about InternetSetOption and InternetQueryOption respectivly. Both require a parameter to tell them which option you are interested in. Have a look at INTERNET_OPTION_PER_CONNECTION_OPTION (for IE5 and later), INTERNET_OPTION_PROXY and INTERNET_PER_CONN_OPTION

In the end, you will be calling InternetQueryOption quite a lot of times and change some settings with InternetSetOption, but you will soon see that it’s not actually worth it: There is always the possiblity that you have not anticipated some obscure setting a user may have which will distrub your application greatly

And additionally, changing the proxy server settings is a task for an adminitrator, not for a simple application. Before asking the question “How can I change the proxy server?”, the question should be “Do I really have to change the proxy server? Isn’t there a better way?”

Refactoring – It’s worth it

Just shortly after complaining about not having time to do some refactoring, I reached a place in my code where it was absolutely impossible to add feature x without cleaning up the mess I created three years ago. And – what’s even better: I had the time do really fix it. Cleanly

What I did was to sit down and recreate the whole module in a new Delphi project. I knew what features I wanted to have when finished and I somewhat knew the interface I had to comply to. The latter proofed inpractical, so I did some modifications to the interface itself (the thing was hacky too). Redoing the whole module took about a week (it’s about downloading stuff, exctracting and then XML-parsing it – everything in a thread while still providing feedback to the main thread), but it was absolutely worth it:

  • The code is clean. And with clean I mean so clean that adding further features will still be clean, depite not being needed as the new framework I’ve created is extremely powerful.
  • The thing is fast. Twelve times faster than the old version. I’m processing 7000 datasets in just 20 seconds now (including time needed for downloading and decompressing) which took me four minutes before.
  • The thing is more usable. Status reporting to the end user went from nearly nothing to everything the user may need. And she can now cancel the process – of course.

A task fully worth of undertaking. I’ve not been that pleased with my code for quite some time now