Tuesday, February 5, 2008

NSIS: Another Gem from Nullsoft

I figure I'll follow a bad review with a good one.

NSIS is a scriptable installation system designed to create Windows installers. It's open-source, free, and becoming more and more popular as time goes on. Google uses it for many of their software applications, as does Yahoo, McAfee, Amazon, etc, etc. You can find a list of more companies using it here.

I used NSIS to create the installer for a certain VB.NET software application I've been developing and supporting since 2004. But NSIS wasn't my first choice. In fact my first choice was InstallShield because that's what the consulting company I was working for at the time had used in the past. I wrote about 20 different installers with it, and they worked pretty well, some of the time. But eventually I got fed up with InstallShield's awful support for what I considered simple custom tasks. When I eventually figured out how to do some of what I wanted, I still faced problems with InstallShield's flaky behavior.

I was determined to find a replacement for InstallShield, so I looked at WISE. It was also a disappointing experience for me as the IDE itself liked to crash on me from time to time as many others have reported. So WISE was out.

I tried a few other installers and eventually I came to NSIS. At first I was skeptical since it was free, open-source, and I hadn't heard of it before. I figured that a free open-source installer like this couldn't possibly compete with the likes of InstallShield and WISE which seem to be regarded as industry standards for some reason.

The thing is, using NSIS is a COMPLETELY different experience from InstallShield and WISE because absolutely everything is done through scripting which can seem like a daunting task at first. But I used the HM NIS Edit tool to build my first NSIS installer. The wizard took me through the basic steps of creating my first installer, and it wrote the code I needed to get started. The code was a little weird at first but I'm a programmer so I got the hang of it eventually. Furthermore, I found the user-submitted code examples and tutorials on their sourceforge site to be very helpful.

I was able to do EVERYTHING I wanted with NSIS. I've been using it on a fairly large scale now for the past 3 years. And I've had absolutely no complaints with flaky behavior from thousands of users now. In the latest release of our completely rewritten software I made the installer first automatically detect if Windows Installer 3.1 is installed, and then download & install it if necessary. Then it'll check if .NET 2.0 (or later) is installed on the machine and download it from Microsoft if it's not. It will also perform a CRC check to ensure the installer itself is not corrupt, assign appropriate file associations for the software, and check if the logged in user has administrative privileges. All of this works perfectly.

On top of that, the final executable NSIS produces is much smaller than an equivalent InstallShield exe. And an NSIS installer performs the installation MUCH faster than InstallShield as well.

So for me it was a no brainer. Once I got over the initial learning curve of NSIS I never looked back. I highly recommend it for any programmer who wants to build good Windows Installer packages for their software.

Adobe Acrobat Hell

Ever tried to use Adobe Acrobat Professional as a word processor? If you have, you might have some idea of what this post is about. I had to make a very very simple change to an existing PDF and it took me an hour to figure out how to do it without screwing up the formatting of the whole document. I ended up selecting the text I wanted to edit and I clicked "create artifact." And then I was able to isolate elements of the document. It was not obvious to me at all that I needed to do that. I was just grasping at straws and found something that worked... kind of. I still ended up screwing up the formatting a little bit, but it'll have to do.

Now I've never been too impressed with the user interface of most of Adobe's products. I've always hated Acrobat Reader especially. I think it's one of the most over-rated, over-used programs out there. But man, this experience was beyond awful and this should have been such an easy task.

Thursday, October 4, 2007

Three ways to improve your website's speed

Other than the obvious server and connection upgrades, there are in fact a lot of optimizations that could be made to your average website and web server configuration to serve up websites faster and save bandwidth.

There are 3 main points:
1.) Code optimization - Use an external CSS file to consolidate common formatting rules for your site. Use short-hand CSS when possible. Remove extranneous whitespace in your HTML, Javascript, and CSS (at the very least -- use a single tab instead of double-spaces).
2.) Content expiration - Enable content expiration for all of your static content. At the very least this should include CSS, JS, and image files. One easy way to do this is to make an "images" folder for your images and an "include" folder for your CSS and JS files. Then you can simply configure content expiration at the web server for those folders. The benefits of content expiration can be huge for both the server and the client. In effect, it prevents roundtrips to the server since it instructs the browser to store the file in its temporary cache for X amount of time.
3.) HTTP Compression - Gzip compression has been supported in browsers for a long time. In fact, it dates back to the IE4 days. But even in the rare case that someone uses a browser that doesn't support it, the web server will be smart enough to send the data uncompressed. The only real penalty is that it takes a little more processing power to compress the files. But in the vast majority of cases CPU time is abundant but bandwidth is not. So these days it's almost silly not to use HTTP Compression. Gzip compression can shrink your HTML, CSS, and JS pages down to 1/3 or sometimes 1/4 the size prior to transferring to the user's browser.

Below are a couple of excellent resources for those of you who want to learn more about these techniques and how to implement them:
- Fundamentals of Web Site Acceleration
- IIS Compression in IIS6.0

Thursday, September 27, 2007

The perils of being responsible for a big website

I maintain and develop a website for an insurance agency. All of our new business starts by someone coming to the website to fill out our online application. So naturally when something goes wrong with the site there's a lot of responsibility on my shoulders.

Now, for the past few days I've been preparing for a web server migration. We were going to move the website and SQL database to a new dedicated server in a datacenter. This morning was the set day to do the big move. I planned everything ahead of time very carefully. I wanted to minimize the downtime and this article was a big help: http://www.sqlservercentral.com/articles/Administering/2688/

The plan was this:
1.) Perform a complete backup of the database
2.) Restore the complete backup onto the new server with NORECOVERY
3.) Take down the online quoting process on the site for everyone except for my IP (for testing purposes), and change the connection string to point to the new server
4.) Perform a differential backup of the database
5.) Restore the differential backup with NORECOVERY
6.) Restore the differential backup with RECOVERY
7.) Test the site and if everything is OK then bring the site back online (still on the old server at this point)
8.) Change the DNS settings

I had tested all of this ahead of time and determined that we should be able to limit the downtime to just about 3 minutes. I don't migrate websites often so I thought I was the man for getting it down to just 3 minutes of downtime.

Well when it finally came down to it the migration didn't go as smoothly as I was hoping. Apparently the production server was set up to block all IP addresses except for those explicitly allowed in an exception list. And in the exception list was the IP I was testing from. So of course my testing worked but when it was pushed to production, it didn't. I didn't know the server had been configured that way and it took me awhile to figure that out. So as a result we had closer to two hours of downtime for the users that still had cached DNS. Realistically, most users wouldn't have had cached DNS so most users visiting the site during that window of time would have seen the site from the new web server. But still -- that sucked.

The good news is everything is configured properly now. The new web server is on a connection with more bandwidth than the old server. And it's a quad-core machine with 4GB of RAM. So it has the power to support us and then some. I also configured it to use HTTP compression (which we didn't have on the old server) and the impact of that can be pretty huge when it comes to download times.

Friday, September 14, 2007

Winamp: Sometimes the small companies do it best

I've used NullSoft's Winamp as my music player of choice for years. It's a free lightweight media player and it does what it does very well. I've never seen it crash. It has always been responsive and quick to start up. And it has an easy-to-use EQ which I always configure to my liking for a particular computer and speaker setup.

Over the years many other media players have come along and they have evolved. Some will automatically download album art when you put in a CD, and they certainly have a lot of other "neat" features. Although honestly I found most of it was extra fluff that I didn't need. Winamp, on the other hand, has taken on many updates and revisions but it's strength is still the fact that it's a simple, efficient, and easy to use music player. I love the fact that Nullsoft has not turned it into bloatware.

For some reason, for a little while I was using one of Winamp's rivals, Windows Media Player on my work computer. I'll tell you what, it's like comparing a 2,000 pound Lotus Exige to a plump 3,500 pound Mustang GT. Winamp is just so "lightweight" and quick to respond to my every request.

Digging deeper I uncovered a shocking difference between the two players. For those of you who like numbers, I ran each one to see how much memory each player would consume while simply playing an MP3 (no visualizations), and running Winamp in "classic" mode.

Here are the results:
Winamp 5.35: 7,608 KB
Windows Media Player 11: 66,508 KB

I also modified a classic skin for myself. It's the RajIOamp2k Special Edition skin which I always thought was extremely well done. But I made it all orange...

In case you like it, you can download the skin here.

Thursday, August 2, 2007

Removing Norton SystemWorks causes problems with Office Automation

This was a tough problem to uncover... so tough that I think it really should be documented. I develop and support some VB.NET 2.0 software which uses Microsoft Word Automation. One user sent me an email with a problem that occurs on his machine when this Word Automation functionality takes place.

This is the error as it was reported:
System.IO.FileNotFoundException: Retrieving the COM class factory for component with CLSID {000209FF-0000-0000-C000-000000000046} failed due to the following error: 8007007e.

I didn't know what was going on but my first suggestion was to try a Word "Detect and Repair." This didn't solve the problem. So I was left to searching Google for potential solutions. I was researching and researching for a couple hours and my hopes were fading.

Then I found something. I found a case where somebody had to manually remove Norton Antivirus, but Norton left behind a registry entry with a bad reference. In this case this bad reference also caused a problem with Office Automation. I thought I might be onto something here. So I asked the user I was trying to help about this and sure enough, he too had Norton installed at one point but had since removed it. At this point I was feeling a bit like Dr. House diagnosing complex medical problems in the show conveniently named, "House."

This user seemed very comfortable with his computer so I asked him to go to the following location in his registry and export and email it to me:
\HKEY_CLASSES_ROOT\CLSID\{000209FF-0000-0000-C000-000000000046}\

The settings here are critical to the operation of Microsoft Word. So I took a good look at his registry settings and found the registry entry of consequence resides at:
\HKEY_CLASSES_ROOT\CLSID\{000209FF-0000-0000-C000-000000000046}\InprocServer32

The (Default) string in this location was "C:\\Program Files\\Common Files\\Symantec Shared\\Script Blocking\\ScrBlock.dll". I had the user double check to ensure that this dll doesn't exist in that physical location. It didn't so I had him right-click that (Default) value and delete it. This solved the problem!

Now apparently Norton can be notoriously difficult to remove completely. I had problems with this myself last year. I don't know if it's typical, or if it only happens when your computer happens to be infected and your Norton installation is crippled, or just what. But in this case it obviously left behind stray information which caused this problem.

Hopefully what I've learned today will be helpful for someone else.