Brendan Enrick

Daily Software Development

Linking to the "I'm Feeling Lucky" Google Search

So one thing I've always loved about Google is the I'm feeling lucky search feature. Most of the time I know that the top result is the one I need. Earlier today, I was googling for how to link directly to the Google results using an "I'm Feeling Lucky" search, and I found one interesting thing. I am not sure how accurate the information is, but it seems that Google loses $110 million per year because of the "I'm feeling lucky" button. Clicking the button means you see no ads from Google, so Google effectively does not get any money from a user who clicks that button.

OK, so by now I would hope that someone is wondering why I would want to create a link which points to an "I'm Feeling Lucky" result. Well it is quite obvious that I want to hide the eventual destination of the link. I am assuming that people will notice that it goes to Google, but will not notice the part of the query string where it really doesn't send them to Google.

So I found out that all you have to add into the querystring is btnI=745. Yes, it is that easy, so Here is a nice example of a link I believe you should all see.

http://www.google.com/search?hl=en&q=french+military+victories&btnI=745

Google-FrenchMilitary

Following the link I have listed above is the same as doing what my screen shot illustrates.

Yes, I think it is a very funny joke. That site has been the top result on Google for that search for a looong time. It is the top result for "french military victories", and is quite a funny result. It could use an update to look like the current version of the Google results page, but it is still pretty nice. I could also link to this site, and send people through Google to get there.

Orcs Goblins and .NET

Have a great day, and don't use this for anything nefarious!

Watch TV Shows on Hulu

Not sure if everyone new about this. I would argue it is not off topic since it is an interesting thing on the web. Hulu is a great new service for watching television shows online anytime. Commercials are short and quick. It is an amazing service I expect plenty of people to start using. I've watched a few shows on there already.

Hulu-Home

I've found the interface quite easy to use and understand. Nothing seems weird or difficult. So when you go to watch a show you might get a message like this before the show starts.

Hulu-AdsQuestion

OK, cool. I can either watch one movie trailer at the beginning or I can have some commercial breaks. Not too shabby. If the movie trailer sounds interesting I will watch it, and if not I'll take the commercials. Trust me the commercials are not bad at all. There are not too many of them, and they are quite short compared to standard television commercial breaks.

Hulu-Commercials

This example I have here is a 1:26 runtime, so that is not too many commercial breaks. Plus, you can see when they are coming . This is a two hour long episode on television, so as you can imagine there are normally more and longer breaks. I've been very impressed with how quickly I can skip to any point in the show and watch. I've never had it lag on me, and it has never given me any loading screens or pinwheels that I often receive from other sites. Not sure how they got everything to stream so quickly and nicely, but you can be sure I will be watching on here a lot now.

If you have not looked at Hulu yet, you really need to. It is an amazing service, and it is free.

SQL Server Client Tools Installation

A while back I blogged about how to install sql server management studio, and it got a reasonable amount of feedback. More recently, Steve Smith posted a response to it where he highlights a better way of installing Management Studio. The method I outlined doesn't seem to work in every instance, so in his response Steve supplied a method which works more often.

The Solution: Run the SqlRun_Tools.msi file found in this folder.

{drive}\ENGLISH\SQL2005\DEVELOPER\SQL Server x86\Tools\Setup\SqlRun_Tools.msi

{drive}\ENGLISH\SQL2005\DEVELOPER\SQL Server x64\Tools\Setup\SqlRun_Tools.msi

Choose the top one for 32-bit systems and the bottom on for 64.

Lots of people keep UAC disabled on Windows, so they'll miss out on nice annoyances like the fact that this method requires you run the msi file as a local administrator. So as I am apt to do, I tried right clicking on it to choose the "Run As Administrator" context menu item. To my surprise it is not there! Below I've supplied the workaround I use in Vista for running as administrator when the context menu item is not present.

One of many ways around running a program as administrator when the context menu item is not present.

  1. In the start menu type "cmd".
  2. When the dos prompt icon is the only remaining icon right click on it and run as administrator.
  3. Copy the file location of the file you wish to run.
  4. Paste the location into the command prompt window.
  5. Click enter.
  6. Watch the program begin with administrator privileges.
  7. Celebrate and enjoy!

Update (9/9/2008): If the software claims that you have nothing to install when you run the SqlRun_Tools.msi then it means that installation has been borked. You will want to try running the Microsoft Installation Cleanup Utility. It will remove the client tools that SqlServer thinks are there, and it will then let you install them.

Windows Vista DreamScene Only Works with 1 Monitor

So I haven't had a lot of problems with Vista. There have been some slight issues including this one I blogged about recently. I think windows DreamScene is very cool, but I of course of more than one monitor attached to my computer. Okay, I can understand that they might have difficulty displaying the DreamScene video on both monitors, but not even allowing it to run because I have my desktop extended is absurd.

I would just like to be able to display it on the primary monitor or something. Perhaps let me pick a monitor and tell me only 1 monitor is allowed. instead of saying that I can't use it at all. I had to disable my second monitor to get DreamScene running.

If DreamScene and a second monitor are enabled at the same time, you'll see this nice popup from Windows.

DreamSceneErrorPopup

And when you click to see more information, it gives you this nice error message.

DreamSceneErrorMessage

Thanks guys.

How hard would it be to make DreamScene only run on 1 of the 2 monitors? Honestly here. let me choose a solid color background color even for the extra monitor(s).

One other request that gripes me a bit. I have plenty of backgrounds I like. I use a Gadget which changes my desktop background at a regular interval, but I wish this were a built in feature of windows. It really shouldn't be that hard, and it is certainly easier than DreamScene.

Have a great day!

Vista 64 Install Requires a DVD Device Driver

So I've been using Vista 32 for a while now. I've not had much trouble with it. I've not seen the horrors about which others speak. Perhaps now my eyes have opened a little bit to some of the problems. So while installing Windows Vista 64 on a machine, the installer said it needed a driver for the CD/DVD device. So at this point I am a bit confused. It makes no sense. If it could boot from the disc why can't it install from the disc. It can read the disc perfectly well. How else could it have booted from the disc?

After scouring a few forums trying to find the answer, I found a few interesting suggestions. While on 3rd party sites, I got suggestions of buying new devices or installing drivers in windows. Some suggestions of getting the drivers loaded during installation. On Microsoft forums I saw a lot of comments saying, "tell company x to write drivers for 64 bit". OK, thanks guys. It is an optical disc drive, and any OS installer should be able to boot pretty much any optical drive with minimal compatibility and install.

I eventually found one suggestion which seemed a bit crazy, "Change the IDE settings". So I figured I would try rewiring the device and see what happened. As it turned out for me if the drive was not set as the secondary slave, Vista 64 would not install. Just try and tell me that doesn't seem crazy.

The Solution that worked for me: Change the IDE settings so that the DVD Drive is the Secondary Slave.

Enjoy Windows Vista 64.

Performance with DropDownLists and ViewState

DropDownList-HornsOne problem I've noticed on a bunch of sites is a large amount of ViewState. I'm not going to sit here and explain all about ViewState. There are PLENTY of sources for information on that piece of technology. So in an extremely short description of what ViewState is I will say that, "ViewState is a way of preserving the state of the 'Viewed' elements of ASP.NET while the page is sent to the client and back to the server."

So what is the big deal? A little bit of extra information stored in a text file. That doesn't take long to download. Download speeds are really quick. WRONG! Sure, it does not take long to download a little bit of extra data, but ViewState is stored in an input control. This is how the data is able to get back to the server so it can reconstruct the previous state of things. This means clients will push the data up to the server. As many of you probably know upload speeds are much slower than download speeds.

OK, so I need to upload a little bit of extra data. How much are we talking about here? It can't be enough to matter.

I'll show you a bit of testing here. I'll create two ASP.NET pages.

Default.aspx

<form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="DropDownList1" runat="server" />
        <asp:Button id="Button1" runat="server" Text="Postback" />
    </div>
</form>

Default2.aspx

<form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="DropDownList1" runat="server" EnableViewState="false" />
        <asp:Button ID="Button1" runat="server" Text="Postback" />
    </div>
</form>

Default.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    // Create my data source (this would normally be data access or something similar)
    System.Collections.Generic.List<ListItem> myData = new System.Collections.Generic.List<ListItem>();
    for (int i = 0; i < 100; i++)
    {
        myData.Add(new ListItem("Element " + i.ToString(), i.ToString()));
    }
    DropDownList1.DataSource = myData;
    DropDownList1.DataBind();
}

Default2.aspx.cs

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    // Create my data source (this would normally be data access or something similar)
    System.Collections.Generic.List<ListItem> myData = new System.Collections.Generic.List<ListItem>();
    for (int i = 0; i < 100; i++)
    {
        myData.Add(new ListItem("Element " + i.ToString(), i.ToString()));
    }
    DropDownList1.DataSource = myData;
    DropDownList1.DataBind();
}

Note: When you disable ViewState you'll want to be binding data to the control during Init otherwise you'll run into some problems, because you'll be binding your data after ViewState has been restored.

These are the only differences between the two pages. So how much of a difference is there? The the amount of data being used for ViewState for the page with ViewState enabled on the DropDownList is 3.07 KB and for the page without ViewState enabled on the DropDownList 52 Bytes. Ok so not too big a deal right? Well imagine if you had a few of these on the page, and maybe the page posts back more than once while being used. Perhaps the hosting server is already somewhat slow. Perhaps you have users on dialup. Keep in mind that if you're setting values from the code for most controls it will end up in viewstate.

Note: Basic form controls will not be using ViewState since they post their values back anyway.

Grab a ViewState Decoder. I use the ViewStateDecoder from Pluralsight. If you use a tool to Decode the ViewState from these pages, you'll notice that the values from the dropdownlist are stored within. It will contain 3 things for each row of the dropdownlist. You'll have the Name of the list item, the value of the list item, and a bool. In total 2 strings and a bit, but since ViewState is all strings anyway this is all stored in a string format.

The spark that formed this blog post. I recently took on some pages with far too much viewstate. They had plenty of stuff on them and none of it had ViewState disabled. I took a page that had html source of 256 KB of data, and I dropped it down to 190 KB of data. It started with 74 KB of ViewState (ouch!) and now has 8 KB of ViewState (w00t!). The page is much much faster. It loads instantly now and when it does a postback it doesn't feel like the application is dying. All it took was removing ViewState from a bunch of controls.

Upgrading to XtraReports version 7.3.6.0

A few weeks ago I upgraded a site using XtraReports to a newer version. I upgraded from 7.1.3.0 to 7.3.6.0 (not a major revision update) and the results were simply amazing. Looking at the version number I would assume that no major changes were made, so upgrading the software should be quite simple right? No, there were plenty of breaking changes for me to update. This is not to say that there is anything wrong with the new version. In fact I love the new version of this product. Why? Because they did change the old crappy implementation of their reporting.

As with most reports it is common to filter the data which will be placed into the report. With the old version of these reports it was fun. Lets just say that the reports previously rendered inside of iframes, so if you tried to use paging in the report it would not be a postback. You'll lose your filter values if you page. OK so you need to have your filtering work whether it is a postback or not, so you need to store it in some form of saved state that will work. Basically you end up storing the values in Session. Yeah. A bit hacky huh? Well, when we upgraded to the new version all of a sudden all of our reports were broken. This is because..... THEY GOT RID OF THE IFRAME!!!! <cue the celebration music> So I happily did a bunch of work removing all of the hacked together code that made the filtering work. Now the code is clear and easy to follow. It is far less error prone.

I like the reports. They're very nice controls, but that previous implementation was a bit crazy. I no longer have my huge complaint about XtraReports. They're now very easy to work with. So if you're using an old version of XtraReports and have seen the problem I mention above, go get yourself the new version of XtraReports even after the extra work you need to do you'll be quite happy.

Good day to you.

C# Generics vs C++ Templates

I regularly meet with a group of my college friends with whom I studied Computer Science. While at a great local bar we have plenty of interesting computer-related conversations. A lot of .NET developers probably spend most of their time discussing technical topics with other .NET developers. Our conversations are much more interesting because everyone there works with different languages and different types of technology. It really adds a lot to our discussions. So as has happened a few times, I mentioned C# Generics. As usual it sparked a conversation about how C# Generics are not as good as C++ Templates. As usual I agree with them. (Yes, I really do like C++ templates better than I like Generics in C#)

So I searched on MSDN, because I wanted to see what Microsoft cites as the key differences between C++ templates and C# Generics. I found this article explaining the differences between C++ templates and C# Generics. OK, I agree these are some important differences. It says on there specifically that they were not even trying to have as much functionality as templates. It is good that they said that, because the list of "differences" could be renamed "reasons why templates are better".

The list of reasons cites a bunch of differences in how they are able to be used. I still want to know the differences in the implementation of them. For that big important difference they have it separated from the nice list. Its in the paragraph of description. They mention one HUGE difference. As they say, "C# generic type substitutions are performed at runtime and generic type information is thereby preserved for instantiated objects." So what is the big deal you might say. There are good things and bad things here for generics.

Since templates are compiled at runtime, the compiler will figure out every version of the template it needs and will create the code for them. This is great because it gives optimal performance. Sure there is a bit more code, but it is nice to not have to create these methods at runtime. With C# Generics, the required code is created at runtime. Ok so that sounds pretty bad. It isn't really as bad as it sounds. Generics are implemented smartly, and because of this it isn't much of a performance issue. So at runtime our code will be created to handle the different types our generic can handle. What if we're going to have a bunch of types? If they're all value types then you could have a problem. It will actually create a completely new implementation of your code for every value type you use for the generic. If you're using a reference type it uses some cool tricks to point to the correct type, so it only has to have one reference type implementation. This means you'll have the performance hit once when you first need the generic on a reference type. Then it is a minimal hit each other time you need it.

Yes, I was a C++ programmer before I learned C#. I hope you enjoyed this post. I appreciate comments. I really like the ones which add something to the post, so if you've got extra information to add I encourage you do so. If I've made any mistakes in this, please let me know.

Unable to cast object of type 'Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection' to type 'Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection'

Earlier today I was trying to track down this error.

Unit Test Adapter threw exception: The type initializer for 'Microsoft.VisualStudio.TestTools.UnitTesting.TestConfiguration' threw an exception. Unable to cast object of type 'Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection' to type 'Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection'

I tried Googling for it, but I didn't find anything regarding this problem. I was pretty sure it was a VS 2008 upgrade issue, because it looks like it is a dll version issue. Since the two classes it is trying to cast between are the same class. So I must be using the wrong version of a dll and I not too long ago upgraded to VS 2008.

In the App.config file there is a config section defined like this.

<section name="microsoft.visualstudio.testtools" type="Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection, Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>

All that needs to be changes is to change the 8 into a 9. Once you make that change all will work once again.

This will work for pretty much any version issue you run into which looks like this. It is funny because the two class names are the same. This is your signal that it is a version issue. The nice thing is that you usually just need to change an 8 into a 9.

I hope everyone is enjoying Visual Studio 2008. Have a great day!

Try Catch Performance in CSharp: A Simple Test Response

I read an interesting little post about a Try Except Performance Test Using Python written by Patrick Altman. As he mentioned, I have also had discussions with people about this exact topic in the past plenty of times. He was testing the performance issue of whether it is better to use a try catch block to handle possible errors or to check for them before they're a problem.

He handled 2 different cases; the success and the failure. Using loops he performed time checks on these to see how long it took. I thought it was very interesting, but the nice question is how does this hold up using C#. So I also wrote a simple little test similar to his. The results are pretty interesting. Keep in mind this just gives some rough estimates on this.

 

The case where the key does not exist:
1,000 iterations:
Try_NotExist(1000) = 00:00:00.0852580
Without_Try_NotExist(1000) = 00:00:00.0000089
Without_Try_NotExist_Not(1000) = 00:00:00.0000089
100,000 iterations:
Try_NotExist(100000) = 00:00:06.1590461
Without_Try_NotExist(100000) = 00:00:00.0006802
Without_Try_NotExist_Not(100000) = 00:00:00.0006799
1,000,000 iterations:
Try_NotExist(1000000) = 00:01:02.8172468
Without_Try_NotExist(1000000) = 00:00:00.0070592
Without_Try_NotExist_Not(1000000) = 00:00:00.0092609

The case where the key does exist:
1,000 iterations:
Try_Exist(1000) = 00:00:00.0000083
Without_Try_Exist(1000) = 00:00:00.0000117
Without_Try_Exist_Not(1000) = 00:00:00.0000117
100,000 iterations:
Try_Exist(100000) = 00:00:00.0006185
Without_Try_Exist(100000) = 00:00:00.0008624
Without_Try_Exist_Not(100000) = 00:00:00.0008492
1,000,000 iterations:
Try_Exist(1000000) = 00:00:00.0088896
Without_Try_Exist(1000000) = 00:00:00.0086661
Without_Try_Exist_Not(1000000) = 00:00:00.0097892

As you can see here my results are somewhat similar to the findings Patrick found. If it is going to fail often at all you're much better off checking for the error before it fails because of how immense the difference between handling the error and not is. However if pretty much every time the code will succeed without any errors, you're better off with the try-catch block by a very small amount. The fact that it is only a small amount better tells me that I am much better off checking for an error than I am using a try-catch block to trap the error.

And so you can try for yourself or inform me of any errors I've made I'll include my code.

using System;
using System.Diagnostics;
using System.Text;

namespace Try_Catch_Performance
{
    class Program
    {
        private static int[] x = { 0 };
        private static int ExistIndex = 0;
        private static int NotExistIndex = 1;

        private static void Try_NotExist(int iterations)
        {
            Stopwatch st = new Stopwatch();
            st.Start();
            for (int i = 0; i < iterations; i++)
            {
                try
                {
                    int y = x[NotExistIndex];
                }
                catch (Exception)
                {
                }
            }
            st.Stop();
            Console.WriteLine("Try_NotExist({0}) = {1}", iterations, st.Elapsed);
        }

        private static void Without_Try_NotExist(int iterations)
        {
            Stopwatch st = new Stopwatch();
            st.Start();
            for (int i = 0; i < iterations; i++)
            {
                if (x.Length > NotExistIndex)
                {
                    int y = x[NotExistIndex];
                }
            }
            st.Stop();
            Console.WriteLine("Without_Try_NotExist({0}) = {1}", iterations, st.Elapsed);
        }

        private static void Without_Try_NotExist_Not(int iterations)
        {
            Stopwatch st = new Stopwatch();
            st.Start();
            for (int i = 0; i < iterations; i++)
            {
                if (!(x.Length <= NotExistIndex))
                {
                    int y = x[NotExistIndex];
                }
            }
            st.Stop();
            Console.WriteLine("Without_Try_NotExist_Not({0}) = {1}", iterations, st.Elapsed);
        }

        private static void Try_Exist(int iterations)
        {
            Stopwatch st = new Stopwatch();
            st.Start();
            for (int i = 0; i < iterations; i++)
            {
                try
                {
                    int y = x[ExistIndex];
                }
                catch (Exception)
                {
                }
            }
            st.Stop();
            Console.WriteLine("Try_Exist({0}) = {1}", iterations, st.Elapsed);
        }

        private static void Without_Try_Exist(int iterations)
        {
            Stopwatch st = new Stopwatch();
            st.Start();
            for (int i = 0; i < iterations; i++)
            {
                if (x.Length > ExistIndex)
                {
                    int y = x[ExistIndex];
                }
            }
            st.Stop();
            Console.WriteLine("Without_Try_Exist({0}) = {1}", iterations, st.Elapsed);
        }

        private static void Without_Try_Exist_Not(int iterations)
        {
            Stopwatch st = new Stopwatch();
            st.Start();
            for (int i = 0; i < iterations; i++)
            {
                if (!(x.Length <= ExistIndex))
                {
                    int y = x[ExistIndex];
                }
            }
            st.Stop();
            Console.WriteLine("Without_Try_Exist_Not({0}) = {1}", iterations, st.Elapsed);
        }

        static void Main(string[] args)
        {
            Console.WriteLine("The case where the key does not exist:");
            Console.WriteLine("1,000 iterations:");
            Try_NotExist(1000);
            Without_Try_NotExist(1000);
            Without_Try_NotExist_Not(1000);
            Console.WriteLine("100,000 iterations:");
            Try_NotExist(100000);
            Without_Try_NotExist(100000);
            Without_Try_NotExist_Not(100000);
            Console.WriteLine("1,000,000 iterations:");
            Try_NotExist(1000000);
            Without_Try_NotExist(1000000);
            Without_Try_NotExist_Not(1000000);

            Console.WriteLine("The case where the key does exist:");
            Console.WriteLine("1,000 iterations:");
            Try_Exist(1000);
            Without_Try_Exist(1000);
            Without_Try_Exist_Not(1000);
            Console.WriteLine("100,000 iterations:");
            Try_Exist(100000);
            Without_Try_Exist(100000);
            Without_Try_Exist_Not(100000);
            Console.WriteLine("1,000,000 iterations:");
            Try_Exist(1000000);
            Without_Try_Exist(1000000);
            Without_Try_Exist_Not(1000000);
        }
    }
}

Happy Error Checking!