Wednesday, October 1, 2008

Slow Run dialog

Over the last few months I've been getting better at using hotkeys for navigating around. One of my most used ones is Windows+R, which brings up the Run dialog.

But every once in a while it's dead slow. So slow I begin to think "did I really press those buttons?" and I press them again. And again. After 10-11 seconds I get four or five Run dialogs up at once. The problem comes and goes. Some evenings it happens all the time, but then it can take days or weeks before I see the problem again.



Today it came back, and I decided I wanted to find out what causes it. I'm having a presentation in a few weeks and don't want to have it popping up during the live demos.

I started up Procmon and began to capture events as I pressed Win+R. After a lot of filtering I found a line with the result set to "BAD NETWORK PATH". Hmm. Sounds suspicious. The path it was trying to open was \\server\employees\frode, which is the domaincontroller at work.

Ok, that sounds reasonable enough. For some reason it's trying to contact the domaincontroller whenever I open the Run dialog. My first thought is that the historylist contains a reference to that server, but after reviewing the list I could not find anything particular. I removed the history list completely by renaming the registrykey HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU. The historylist is now empty, but still it would take about 10 seconds to open the dialog.

I recognized the path it was trying to open as my %HOMESHARE% path. Opened up cmd.exe, and ran the Set command. Amongst the variables I saw the following three:
HOMEDRIVE=Z:
HOMEPATH=\
HOMESHARE=\\server\employees\frodel

Hm, Z: is a mapped drive to the server at work. When I left work today I put my laptop in Hibernate mode by just closing the lid, and it's just been awaken again here at home. So that means that Z: is still my homedrive, but that is not an accessible drive from home. Z:\ is still a mapped drive, but not a functional one.

In cmd.exe i tried the following, and received an errormessage 10 seconds later:
C:\>%HOMEDRIVE%
The network path was not found.

I think we're getting somewhere!

Rebooted the computer, and this time the environment variables were set like this:
HOMEDRIVE=C:
HOMEPATH=\Users\frodel

The Run dialog is now 100% responsive, and I'm pretty sure it was because %HOMEDRIVE% and %HOMESHARE% was referring to the server which wasn't available.

Sunday, September 21, 2008

Using state server with ASP.NET

At work we deal a lot with the web version of SuperOffice CRM, and lately I've been trying to figure out why one of our customers users keep getting logged out all the time. Through a dialog with the core technical persons at SuperOffice we've tracked it down to the Session being lost.



Most likely the session is lost because the Application Pool is recycled for some reason. There are several thing which could cause such a recycle.
- web.config being changed
- files in \bin or \App_code directories are modified
- any of the conditions in Process Model for the Application Pool is met. Like a memory limit being hit, or a request-queue being full.
- antivirus or similar modifying the above files

Because of all of this I've researched what it takes to move the session state handling out of the w3wp.exe process, and it's actually not that difficult.

Session state can primarily be handled in three ways. In-Process, with State server or in SQL server. There is also a Custom way, but that's out of our scope for now.

Moving from In-process to using the State server is as easy as modifying a single line in your web.config, and making sure the Windows Service called ASP.NET State Service is running. The web.config should include a sessionState element, like this.

<configuration>
<system.web>
<sessionState mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
cookieless="false"
timeout="20">
</sessionstate>
</system.web>

And that's it!

What we've gained by doing this is that the changes listed above will no longer cause a user to be logged out. You can even call iireset.exe, and the session is still kept alive. What we've lost is about 15% performance since the session needs to be serialized out from the w3wp.exe process, and handled by the aspnet_state.exe process.

If the ASP.NET State Service is restarted it will loose all the sessions since they are kept in-memory by the service.

We can also take this one step further by storing the sessions in a SQL database instead. By doing this we gain even more recilience because we can reboot the server which handles the sessions, and users are still maintaining their sessions when the server is online again.

In order to set up SQL handling of the sessions you'll need to modify the web.config again, but also have a SQL database to store the sessions in.

<system.web>
<configuration>
<sessionState mode="SQLServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString= "data source=127.0.0.1;
user id=sa;password=secret"
cookieless="false"
timeout="20">
</sessionstate>
</system.web>
</configuration>


And the SQL database is created by a tool that ships with the .NET Framework.

C:\>aspnet_regsql.exe -S localhost -U sa -P secret -ssadd -sstype p

That command will create a database on the local SQL server called ASPState where all the sessions are stored. The drawback of storing sessions in SQL is that you loose about 25% performance compared to the InProc mode.

Saturday, September 6, 2008

Cosmos is expanding

I've been putting down a lot of time working on the Cosmos project over the last few months, and it's fun to see all the progress we've been making.

The network driver for the RTL is complete enough to send and receive the data we want, and currently further development for RTL and UDP is continued by Chad Hower (here and here).

I've moved over to filesystem, and am working with the Virtual Filesystem layer. Currently it's working on top of the Ext2 filesystem, but the purpose of this layer is to be filesystem independent. We can enumerate directories and files using classes in the System.IO namespace, but I haven't begun to read inside files yet. For that we are going to need support for Streams.

Often during the development I come across certain basic parts of the .NET framework which break our build, so I keep going back to the absolute basics to fix those as well. As an example I added lots of Console.Write and Console.WriteLine overloads, since we were unable to print lots of basic types. Today I fixed Boolean.Parse(string) and Boolean.TryParse(string, out bool).

I believe it's important to get all this basic functionality in place as well, not just features like network, filesystem and compilation speed. It'll be a lot easier for newcomers to get started if we have all the basics in place.

Friday, August 29, 2008

Flashing my new BIOS's

My stationary computer started acting up and would not let me reinstall an operating system on it a couple of weeks back. After replacing most of the peripheral devices without any luck I decided to buy a new motherboard, CPU, RAM etc.

I ended up with a Gigabyte MA790FX-DS5, running a AMD Phenom 9850 and 4GB of Corsair RAM. I choose a low end videocard, Sapphire Radeon HD 2400, since I'm not much of a gamer anymore.

The Radeon card seems to be non-compliant with my Dell 20" monitor, and refuses to display an image using DVI cable. I got it working with a S-VHS cable, but the graphics are horrible. I see that Sapphire has released a new BIOS for the videocard claiming to "(...)fix bug with Samsung DVI-D(...)". Hopefully it'll also work with my DVI-D monitor.

Flashing a BIOS isn't always straightforward. Finding out HOW you flash, that is.
After googling around I found a way to flash my motherboards BIOS, and I'll put the receipe here for my own future reference.

I tried using the @BIOS application to flash the Gigabyte card. Didn't work. Couldn't connect to any of the online servers.

I also tried the ActiveX driven Download Center on the Gigabyte website. No luck.

Here is what I ended up with:
1. Download new BIOS from MA790FX-DS5 page. My old BIOS was F5, and the newest available was F6.
2. Extracted the files onto a floppy disk.
3. Rebooted computer and pressed END to get to QFlash application.
4. Choose floppy drive, and the .F6 file.
Flashing complete.

Now for finding out how to flash the ROM on the Radeon card.

Monday, July 21, 2008

Which driver?

After coming back from lunch today I was greeted with this dialog on my fully patched 2008 Server:


Huh? Which driver is it complaining about? I even clicked the "See details" linklabel, but it doesn't give any more relevant information?

Who designed this dialog? Why didn't anyone of the dialog-approving-committee over at Redmond raise their hand and say "Shouldn't we show the name of the driver?".

Sometimes I don't get people...

Fortunately I remember starting installation of VMWare Server before going to lunch, so I assume it is a VMWare network driver it is trying to install. I can't be sure, but I'm taking my chances.

I'll just click the "Install this driver software anyway" - otherwise known as the "I want to work today button".

Monday, April 28, 2008

Calculating remaining time


It might sound strange, but one feature I really like in an application is the ability to estimate remaining time. Wheter it is the time it will take to install an application, copy a file or perform another lengthy process.

The last time I came across such an application was while installing TrueCrypt. It has a fantastic timer which updates itself continously during the installation.

Here is a method I wrote for Cosmos for determining how much time remains for compiling the operating system. The method takes two arguments, one for how far we've come in the process, and one for the total length of the process.

The major strength of this method is that it continously recalculates how much time remains. So no more "1 second remaining" for minutes, or grossely missing the target by estimating years to copy a single file.

public static System.Diagnostics.Stopwatch xBuildTimer;
public TimeSpan CalculateRemainingTime(int completedCount, int totalCount)
{
    if (xBuildTimer == null)
    {
        xBuildTimer = new System.Diagnostics.Stopwatch();
        xBuildTimer.Start();
    }
 
    long percentComplete = (completedCount * 100 / totalCount);
    if (percentComplete == 0) //Avoid Divide by Zero
        percentComplete = 1;
 
    long remaining = (xBuildTimer.ElapsedMilliseconds / percentComplete) 
        * (100 - percentComplete);
 
    return new TimeSpan(remaining * 10000);
}

Saturday, April 5, 2008

The joy of Extension Methods in C# 3.0

I discovered a new addition to C# 3.0 called Method Extension while I was writing a convertor for Hex and Binary for Cosmos today. Method Extension is a technique for "spot-welding" methods on to existing classes or types.


    //Without C# 3.0 Method Extension
    if (IsOdd(7))
        ;
 
    //With C# 3.0 Method Extension
    if (7.IsOdd())
        ;


Here the I've added the IsOdd method onto an integer type. I think the lower example is a lot easier to read than the upper.

Adding an extended method is as simple as adding 'this' keyword on the first parameter on a static method inside a static class, like this:


public static class IntExtender
    {
        /// 
        /// Checks if number is odd or even.
        /// 
        public static bool IsOdd(this int n)
        {
            if ((n % 2) > 0)
                return true;
            else
                return false;
        }
    }


Method Extensions requires a reference to System.Data.Core assembly in your project.


The Intellisense looks like this:














By adding extensions in Cosmos we can now directly convert numbers to Hex and Binary like this:

foreach (byte b in bytes)
    {
        Console.Write(b.ToBinary());
        Console.Write(b.ToHex());
    }