Tuesday, June 27, 2006

What do the following have in common?

What do the following have in common?

The answer is not this.  These are the previously announced features of Microsoft Vista that have been dropped out of the product over the last couple of years.  Here’s a link to a good article with the gory details…

At the rate features are being being axed, at what point does Vista come XP SP3? It’s becoming XP with tighter DRM, and who wants more of that?  Of all of the stuff that’s been yanked, WinFS was the one that I really wanted.  I really hoped that MS could have pulled it off.

On the other hand, it just sounded too complicated to actaully pull off.  Having your file system be dependant on SQL Server requires a lot more under the hood with that much more resources required.  To a certain extent, the desktop search tools that came out in the last two years made the need for WinFS less important.

Tomato funeral

I saw a reference to “tomato funeral” on a .Net developer’s blog.  I had to click through the link and ended up somewhere deep in the bowels of Wil Wheaton’s blog….

My friends and I have, in the past, enjoyed playing a game we affectionaly call "tomato funeral". Often when we find ourselves in close but temporary proximity to a stranger or group of strangers (like being in an elevator) one of us will start the game by turning to the other and asking:

"So then what happened?"

At this point it's the goal of the other person to come up with the most nonsensical but still plausible conclusion to a conversation that will presumably leave the strangers wondering for the rest of the day what possible situation could have led up to that phrase. The game is named after one of the earliest successes:

"Oh, well, she went to the funeral, but, well, you know, I doubt she'll ever eat tomatos again"

Points are awarded for creativity and quickness of response.
http://www.wilwheaton.net/mt/archives/001827.php#c109100

 

Tuesday, June 13, 2006

Fun with scripted load tests

We are getting ready to do some load tests and it's time to pick some tools.  The app that we want to test is a client/server app with buckets of processing going on the client side.  Most c/s load test tools just emulate the traffic that goes on between the client and the server.  For our app, that wont work, the load occurs on both the client and the app and we have to drive the app.  This means one instance of the app per PC.  We have tried multiple instances of the app on the desktop or through multiple terminal service sessions, but that just didn't work.  We tried that a couple of years ago at at the Microsoft testing facility in Waltham, MA, but it only would work as one app per machine.

So we will just do that here in the office.  Some night, after everyone goes home, we'll log into each desktop with a special login (limited access) and run our tests.  We are evaluating HighTest Plus, from Vermont Creative Software.  It's an automated software testing tool that allows you to record and playback keyboard/mouse actions.  What we want to do is to setup a repository of scripts and have a set of PCs run the scripts.  The fun part is how to start each testing session without having to walk over to each machine and login and then run the script.

I first looked into somehow getting each machine to login into the testing account.  There's no easy way to remotely script this.  For security reasons, you have to use the keyboard and/or mouse with the login dialog, you can't bypass that with a script invoked from another machine.   We didn't want to install any remote access software like VNC or pcAnywhere.  It would cost too much and we didn't want to leave anything running on the machines during business hours.  That leaves Remote Desktop.  You can script the mstsc.exe client so that you can feed in the login infomation.  So we started with that.

We wanted to start the remote desktop sessions and then disconnect from them, with the sessions running.  The reason for this was that the machine controlling the tests would end up with 10 to 40 remote desktop sessions and there could be a resource problem.  We tried using Sysinternal.com's excellant psxec utility to remotely invoke the HighTest executable.  No matter hoiw we sliced it, it would fail with msg hook error message.    This meant that we had to invoke HighTest from a process running on the remote pc.  After banging a few things around, I created a batch file on the remote pc to launch the HighTest executable and added the the "Scheduled Tasks" list.  That worked, so I disabled the task so it wouldn't get launched by accident.  The schtasks.exe can be used to run scheduled jobs, even from other machines.  Provided that the machine has an open desktop and is not a disconnected session.  Disconnected sessions do not receive keyboard or mouse input, not even simulated input from HightTest.

We have once more trick up our sleeves.  The remote desktop client (mstsc) can be configured to run a program after you are connected.  If you have the "Remote Desktop Connection" dialog open, click on the "Programs" tab and you will be able to configure the program that you want to run.  We we will do is to have it run a batch file.  That batch file will run the HighTest tool, do any cleanup, and then logout.  And that's how we plan on running our load tests.

[Edited on 6/14/06]
Scratch the running of programs from the "Remote Desktop Connection" dialog.  That only works if you are connected to a Terminal Server.  You get bupkis if you use that option with Windows XP.  We are back to looking at using schtasks.exe after starting the remote session with Remote Desktop.

Tuesday, June 06, 2006

Self installing services in .NET

I have some service applications that I deploy with Wise for Windows. These particular services are .NET assemblies. The usual way of registering the .NET assembly as a service is to use the installutil.exe that comes with the .NET Framework. Wise made it easy to register the assemblies by adding a checkbox in the file properties for self installation. Behind the scenes, Wise must be calling installutil, because it fails when you have multiple versions of the .NET Framework installed. Installutil is not compatible across Frameworks. You can’t install a 1.1 assembly with the 2.0 installutil, and vice versa.

Wise does not let you specify which version of the Framework is being used by a particuliar assembly. It should be able to tell through Reflection, but it doesn’t. This means I can’t specify the correct installutil to use for my services. This is not good and causes my install projects to go down in flames. I really can’t wait for Wise to fix this.

I could call installutil directly, but that means putting all sorts of fugly code into the install project to correctly locate the appropriate version of installutil. And that code would probably break the minute Microsoft updates the .NET Framework. So we move to Plan B, self-installing services. You would think that this would be a simple walk through the MSDN garden, but their code examples assume that that task is being handled manually via installutil or through a Windows Installer project.

After a bit of Googling, I found a reference to an undocumented method call, InstallHelper, in the System.Configuration.Install.ManagedInstallerClass class. By using this method, I can install or uninstall the service from the command line.

I augmented the Main() function in the service class to look like this:


static void Main(string[] args)

{

if (args.Length > 0)

{

if (args[0] == "/i")

{

System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });

}

else if (args[0] == "/u")

{

System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });

}

else if (args[0] == "/d")

{

CollectorService MyService = new CollectorService();

MyService.OnStart(null);

System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);

}

}

else

{

System.ServiceProcess.ServiceBase[] ServicesToRun;

ServicesToRun = new System.ServiceProcess.ServiceBase[] { new CollectorService() };

System.ServiceProcess.ServiceBase.Run(ServicesToRun);

}

}


The “/d” part hasn’t been tested yet. That should allow me to debug the service as an application from within the Visual Studio IDE. As much as I dislike having to use an undocumented class, I’m not going to lose any sleep over it. Microsoft obsoleted documented functions going from Visual Studio 2003 to 2005, I’m not going to worry about one method.

[Edited on 6/8/06]
I updated the block of code for the "/d" part. I needed a timeout to keep the service running, otherwise it just runs through the startup and then exits. You can make it fancier, I just use that code for testing from within the IDE and I can break out of the service when I am done testing it.

[Edited on 7/20/06]
After a few go arounds with Wise Technical Support, I sent them a sample installer project that easily duplicate this bug and they did confirm that it was a problem with their current product. There is also a similiar problem where you can't install .NET 1.1 services under similiar circumstances. Their fix for my problem will fix the .NET 1.1 service problem too. According to the email that I had received, this is tentatively scheduled for the next release. That would probably be the version 7.0 release. In the meantime, I'll stick with my work around.

[Edited on 1/27/08]
The MyService object in the above code is an instance of a System.ServiceProcess.ServiceBase descendant class that I created in my code.  The descendant class opens up access to the protecteded OnStart() method.  I had created a descendant to ServiceBase and had assumed that was the standard pattern.  I should have been more clear about that part.  This is one of the many reasons why I abandoned Wise for InstallAware.