In my previous blog post, I’ve mentioned that I’m working on a project to migrate an entire product line to Vista. What I meant by that is that I am responsible for making sure that our current product will run properly on Windows Vista. To guarantee that it is indeed Running Properly it should behave *exactly* like it behaves in Windows XP. In simple terms, my entire job security is riding on making our products compatible with Microsoft’s failed attempt at a MAC-ish Operating System and with Microsoft’s successful attempt (a first in their history) to make their operating system NOT backward compatible with older applications. So much for Raymond Chen’s camp undying obsession with backward compatibility.
This products that I’m talking about are a set of Web Applications written in ASP.NET version 1.1. This web applications are as old as Windows XP.
I checked its File Modification History in our TFS repository and the last time that anyone have touched its code base is in 2005 — and that’s just for a minor code modification to fix a bug. I believe this apps were written way way back in 2004 — when I was in Third Year High School!
To make this products compatible with Vista, there are a couple of steps that had to be done. I’ll enumerate each steps and what it takes to accomplish them.
.NET Upgrade (.NET 1.1 to .NET 2.0)
Windows Vista comes pre-installed with .NET 2.0 (and .NET 3.0). Our products are running on .NET 1.1. One approach that most people will suggest is to just install .NET 1.1 on Windows Vista and everything will be perfect. Right? WRONG. Firstly, .NET 1.1 has already reached its end-of-life. Microsoft pulled support for .NET 1.1 last October 14, 2008. Although it was extended, its a sign that this technology is old enough to be replaced. Secondly, installing .NET 1.1 on a Vista machine is not as easy as you think. No, we are not lazy programmers, we just don’t want to introduce unnecessary complications to the system. We are, by the way, Software Developers.
So the approach we took is to upgrade our Visual Studio 2003 solutions to Visual Studio 2005 solutions. This, in turn, will “force” the web application to use .NET 2.0. You might say, “How hard could it be? Visual Studio 2005 can convert old solutions automatically using its Upgrade Wizard. All you have to do is click next!, You lazy programmer!”. That’s correct. Upgrading the solution is no problem. Converting every file to .NET 2.0 compliant code is.
We encountered two conversion problems. The first one is relatively simple to fix. It’s a problem where the old .NET 1.1 Resource files (*.resx) were not converted to the .NET 2.0 resource files. The two resource file formats are different (the .NET 2.0 have a *.designer.cs component) and in very rare cases, the .NET 1.1 *resx files won’t work in .NET 2.0. This problem is very hard to catch since the incompatible *.resx files won’t throw a compile error. The strings just won’t be detected. But once found it was relatively easy to fix. After a day of investigation, we found out that the XML format for the resource files changed in .NET 2.0. As a simple hack (fix), we manually changed the <string> parameters of each .NET 1.1 strings to match the .NET 2.0 <string> parameters.
The second problem is harder to find and much much harder to fix. The problem is related to ASP.NET’s datetime picker control.
On our previous version running .NET 1.1, there is no problem with the datetime picker. But when we installed the .NET 2.0 version, the calendar objects are all over the place.
Two days of investigation later, we found out that the previous developer made this custom Calendar control by inheriting from .NET 1.1’s System.Web.Controls. During pre-render, he reads the rendered Calendar Control’s HTML and then does something funny with it. What he wanted to achieve is to replace the “Month” from the Calendar header (gray part) with a drop down box that contains a list of the months. So what he did is he “catch” the HTML stream from the Calendar Control and perform a String.Replace on it!
The actual String.Replace command is something like this:
//szHTML = Get current HTML stream //szCurrentMonth = Get current month from HTML szHTML.Replace(szCurrentMonth, " <select><option value="January">January</option> <option value="February">February</option> <option value="March">March</option> <option value="April">April</option> <option value="May">May</option> <option value="June">June</option> <option value="July">July</option> <option value="August">August</option> <option value="September">September</option> <option value="October">October</option> <option value="November">November</option> <option value="December">December</option> </select> ");
It worked fine before the migration, but somehow we broke it during migration to .NET 2.0. A further investigation of the “emitted” HTML stream from the .NET 2.0 control shows this:
<table style="border-style: solid; border-width: 1px; border-collapse: collapse;" title="Calendar" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td style="background-color: Silver;" colspan="7">
<table style="width: 100%; border-collapse: collapse;" border="0" cellspacing="0">
<tbody>
<tr>
<td style="width: 15%;"><a style="color: Black;" title="Go to the previous month" href="javascript:__doPostBack('ctl01','V3378')"><</a></td>
<!-- THIS WILL BE THE PART THAT WILL BE REPLACED BY A DROP DOWN BOX -->
<td style="width: 70%;" align="center">May 2009</td>
<td style="width: 15%;" align="right"><a style="color: Black;" title="Go to the next month" href="javascript:__doPostBack('ctl01','V3439')">></a></td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<th align="center" scope="col">Sun</th>
<th align="center" scope="col">Mon</th>
<th align="center" scope="col">Tue</th>
<th align="center" scope="col">Wed</th>
<th align="center" scope="col">Thu</th>
<th align="center" scope="col">Fri</th>
<th align="center" scope="col">Sat</th>
</tr>
<tr>
<td style="width: 14%;" align="center"><a style="color: black;" title="April 26" href="javascript:__doPostBack('ctl01','3403')">26</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" title="April 27" href="javascript:__doPostBack('ctl01','3404')">27</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" title="April 28" href="javascript:__doPostBack('ctl01','3405')">28</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" title="April 29" href="javascript:__doPostBack('ctl01','3406')">29</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" title="April 30" href="javascript:__doPostBack('ctl01','3407')">30</a></td>
<!-- THE TITLE ATTRIBUTE WAS ALSO REPLACED ACCIDENTALLY -->
<td style="width: 14%;" align="center"><a style="color: Black;" title="May 01" href="javascript:__doPostBack('ctl01','3408')">1</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" title="May 02" href="javascript:__doPostBack('ctl01','3409')">2</a></td>
</tr>
.....</tbody></table>A comparison with the “emitted” .NET 1.1 control shows this:
<table style="border-style: solid; border-width: 1px; border-collapse: collapse;" title="Calendar" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td style="background-color: Silver;" colspan="7">
<table style="width: 100%; border-collapse: collapse;" border="0" cellspacing="0">
<tbody>
<tr>
<td style="width: 15%;"><a style="color: Black;" title="Go to the previous month" href="javascript:__doPostBack('ctl01','V3378')"><</a></td>
<!-- THIS WILL BE THE PART THAT WILL BE REPLACED BY A DROP DOWN BOX -->
<td style="width: 70%;" align="center">May 2009</td>
<td style="width: 15%;" align="right"><a style="color: Black;" title="Go to the next month" href="javascript:__doPostBack('ctl01','V3439')">></a></td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<th align="center" scope="col">Sun</th>
<th align="center" scope="col">Mon</th>
<th align="center" scope="col">Tue</th>
<th align="center" scope="col">Wed</th>
<th align="center" scope="col">Thu</th>
<th align="center" scope="col">Fri</th>
<th align="center" scope="col">Sat</th>
</tr>
<tr>
<td style="width: 14%;" align="center"><a style="color: black;" href="javascript:__doPostBack('ctl01','3403')">26</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" href="javascript:__doPostBack('ctl01','3404')">27</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" href="javascript:__doPostBack('ctl01','3405')">28</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" href="javascript:__doPostBack('ctl01','3406')">29</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" href="javascript:__doPostBack('ctl01','3407')">30</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" href="javascript:__doPostBack('ctl01','3408')">1</a></td>
<td style="width: 14%;" align="center"><a style="color: Black;" href="javascript:__doPostBack('ctl01','3409')">2</a></td>
</tr>
.....</tbody></table>Executing the String.Replace command in the .NET 1.1 code will produce the proper output. However, Microsoft decided to upgrade the Calendar control in .NET 2.0 by adding a tooltip for each date!
Since the String.Replace has no checking (this is not REGEX afterall), it also replaced the “Month” in the tooltip with the drop down box (<select> command), thus generating the broken control shown above. This is not, in anyway, the fault of the original developer. Can you anticipate what will Microsoft do?
This is my first encounter on how Microsoft can break your products. ![]()
MSDE to Microsoft SQL Server 2005 Express
Our web applications were written before the release of SQL Server 2005 Express. The only *free* choice back then is Microsoft SQL Server Desktop Engine, a free scaled-down version of Microsoft SQL Server 2000. Since the support for MSDE officially ended last April 8, 2008, we are then forced to upgrade to Microsoft SQL Server 2005 express.
Our previous MSDE setup runs on default instance. In migrating to SQL Server 2005, we run the risk of “conflicting” with our other products that runs on default instance of SQL 2005. So the decision was made to migrate from default instance to named instance.
Migrating to SQL Server 2005 Express is straightforward at first look. The first and the most obvious thing to do is to modify the installer (InstallShield) so that it will install SQL 2005 instead of MSDE. To compensate with the instance problem, the second thing to do is to modify each and every connection string in the entire app to point to the proper named instance. Making sure that each and every connection string in your entire app has been changed is a monumental task… especially if different version of connection strings were used. After that, you also need to modify the Service Query String so that it will point to the proper SQL Service ($MSSQLSERVER to $Instance_Name). There are also minor modifications here and there, but its not worth the mention.
After three days of manual modification, we got to the point where we were able to install the product. We tested it and everything seems to work fine. We then got to the part where are going to test for the database backup. Lo and behold, it failed. But no error message was given. We looked for the bug for an entire day but our search proved futile. We called it a day and went home. The next day, my brilliant manager excitedly told us the problem.
Microsoft SQL Server 2005 Express does not have SQL Server Agent.
Our backup routine uses SQL Server Agent. When a user request for a backup, the SQL Server will “schedule” that backup request and the SQL Server Agent will “execute” the request when the schedule parameter is met.
Simply put, No SQL Server Agent, No Backup.
We have three solutions to the problem:
- Ship the product with Microsoft SQL Server 2005 standard or enterprise edition (Instead of the Express edition)
- Remove the “scheduled” backup. Instead, just provide a “one shot” backup
- Create our own custom “Backup Scheduler” using Windows Task Scheduler
We talked to the marketing folks and they eliminated option 1 because, according to them, we can’t make our customer pay for something that was free before. Option 2 was eliminated due to the simple fact that we can’t ship an upgraded version of our product with downgraded features (But this was actually done to one of the product that had missed its deadline). So Option 3 was our only choice.
The plan in creating Option 3 is simple. Create a “scheduled task” using schtasks.exe that will invoke sqlcmd.exe that will invoke the sql command to invoke the stored procedure that was doing the backups. The schtasks will then be invoked by the ASP.NET page using Process.Start();. So I created a wrapper class that will simplify this process. The class was created in 2 hours and I had it running and compiled to the ASP.NET page in just 3 hours. BUT IT DIDN’T WORK.
Further investigation revealed that IIS 6.0 has a different security model than IIS 5.1 (which XP uses). Spawning a process from within IIS 6.0 will have a credential of NETWORK SERVICE. Yes, we can impersonate since we are using Windows Authentication, but it won’t work unless we force the user to type-in the credentials again. Which is bad in a usability point of view.
The workaround was to put the scheduler on a Windows Service that will then be run with proper credentials. The problem then was the communication between the ASP.NET page and the Windows Service. How will the Service know when to invoke the backup? Our solution is a little crude but simple. We did it old-skul UNIX style! The ASP.NET page will create a “marker” file in a certain, defined location. The Windows Service will then monitor that location… waiting for the “marker” file. If the marker file is found, the service will then invoke the backup procedure.
Fortunately for us, all the data needed for the backup is in the database, so we don’t need to pass anything between the ASP.NET page and the Service.
We could have used sockets or mutex, but its overkill for our purpose.
This are just the major steps that had to be done in order to make our web applications compatible with Windows Vista. There are a couple of minor steps that also needs attention like the IIS 5.1 to IIS 7.0 migration and the new Vista Security Model.
The next time you see the “Vista Compatible” sticker on a Software Box, think of the programmers who nearly died in making your software run on a “cuter” operating system.


































































Microsoft SQL Server 2005 Express <<< that's why it is called express, its not meant to be used for an enterprise scale… that's why back up is not included on the said software.
Right.
But all I’m asking for is the SQL Server Agent support, not a backup utility.
okay. I was shocked with the terminologies but it recently came to my attention that Vista sucks big time. and sad thing about it, my laptop keeps on having that blue screen aka “Crash Dump”.
Well, I’ve stumbled upon (sounds familiar?) a article online. It was discussing why Microsoft left any kind of backwards compatibility to older Windows versions. It was mainly for the purpose of avoiding bugs that would conflict by adding milions of line of code just to add backwards comaptibility for older programs, or as he calls. “OLD PROGRAMS”.
I do agree with the artcle that anything that will not run proprly, which he defines as having the inability to run at about 70% of its intended operating abilities, is an OLD program. While those that can still run at right around 90% and has a few cosmetical problems, are OLDER programs…… which means he meant that OLD is REALLY OLD, while OLDER is just a few lines of code behind.
Microsoft understands that these OLD programs are often business critical applications, but they didn;t want to risk wasting time fixing a good OS just because of bug caused by compatibility codes. So then, starting WIndows 7, Microsoft is stripping down almost all legacy compatibility to its operating system. Thus making it faster, and easier to fix, incase bugs are discovered. Thus, to allow businesses to be able to run OLD programs, Microsoft has decided to add XPM (WIndows XP Mode) which allows users to run a seemless virtual machine that would run XP applications as if it was installed on the host machine. Although, based on my experience with XPM it was a terrible experince…. but since Win7 and XPM are both not yet ready for primetime, I do hope they get XPM to work better.
So now, Microsoft encourages the developers of the OLDER programs to update their programs to comply with Vista standards. Becuase we all know that Win7 is built from Vista, thus anything that works on Vista should virtually work on Win7 properly. This might be a pain for the developers and certain users but this allows us to move further ahead instead of holding on to the past which slows down the process of improving technologies.
I hope I made a few points that relate to your article today.
P.S. have you tried Windows 7 RC? Its the bomb! I’m using it now on every computer I have! I;m loving it already! I don’t want to go back to XP or Vista anymore!! lol
Good point. Yup, I’ve read that article too.
I haven’t tried 7 yet. I’m still using XP here at home. My next OS will be Vista since I don’t want to miss all the fun of it.
After a year or two, I’ll be using 7 then. I’ll let them iron out the bugs first.