Friday, April 27, 2007

VladStudio: Excellent Desktop Wallpaper Resource

I'm a little neurotic about my desktop wallpaper. As a developer, I spend an inordinate amount of time staring at my computer. Granted, I'm rarely looking at a blank desktop but I like to have something tasteful and artistic when I want to access something on my desktop with my Win+D key chord.

One day I was sitting by a business analyst while collaborating on a project and noticed his nice desktop image. He introduced me to VladStudio, a Russian artist who has been pumping out hundreds of beautiful designs. He even has a system tray application called Companion than can change your wallpaper based on a custom schedule or whenever you just decide you need a new look by just double-clicking the system tray icon.

He provides low-resolution images for free that are still gorgeous. But you can get lifetime access to high resolution images for under $30.00 US. The registration is worth it if only to help him to keep creating designs. I registered several months ago, and he has since added widescreen resolutions images that look even better on my big wide Gateway.

The best part is the the images are very tasteful. I never have to worry about walking away from my workstation and returning to find an email from the HR department. Now I have people asking me where I got my nice desktop image. :-)

Submit this story to DotNetKicks

JavaScript String.format() method.

A while back I worked on a pretty heavy duty JavaScript interface that required, as is typical in any UI, a lot of string manipulation. I became tired of building strings with concatenation, they had a tendency to get unwieldy. I wrote this simple string formatting utility for building strings similiar to C#.

The best way to use it is to put it into an external JavaScript source file and reference it throughout the project.

Although the method has only one defined argument it will accept any number of arguments. If you provide more or less arguments than you define in your string they will not cause an error, they will be ignored.

String.format = function( text )

{

    //check if there are two arguments in the arguments list

    if ( arguments.length <= 1 )

    {

        //if there are not 2 or more arguments there's nothing to replace

        //just return the original text

        return text;

    }

    //decrement to move to the second argument in the array

    var tokenCount = arguments.length - 2;

    for( var token = 0; token <= tokenCount; token++ )

    {

        //iterate through the tokens and replace their placeholders from the original text in order

        text = text.replace( new RegExp( "\\{" + token + "\\}", "gi" ),

                                                arguments[ token + 1 ] );

    }

    return text;

};



You can test the method with these simple tests.

//simple tests

document.write( String.format( "no tokens<br />" ) );

document.write( String.format( "one token, no args ({0})<br />" ) );

document.write( String.format( "one token, one args ({0})<br />", "arg1" ) );

document.write( String.format( "one tokens, two args ({0})<br />", "arg1", "arg2" ) );

document.write( String.format( "two tokens, two args ({0},{1})<br />", "arg1", "arg2" ) );

document.write( String.format( "two tokens swapped, two args ({1},{0})<br />", "arg1", "arg2" ) );

document.write( String.format( "four tokens interwoven, two args ({0},{1},{0},{1})<br />", "arg1", "arg2" ) );

Submit this story to DotNetKicks

Free Image: Old Timey Register

From Creative Commons

Submit this story to DotNetKicks

Free Image: Old Wheel by a Tree

From Creative Commons

Submit this story to DotNetKicks

Free Image: Golden Gate Goes By

From Creative Commons

Submit this story to DotNetKicks

Free Image: Windmill Overhead

From Creative Commons

Submit this story to DotNetKicks

Free Image: Tilted Windmill

From Creative Commons

Submit this story to DotNetKicks

Free Image: Windwill at Dusk

From Creative Commons

Submit this story to DotNetKicks

Free Image: Sunset Over the Waves

From Creative Commons

Submit this story to DotNetKicks

Free Image: Waves

From Creative Commons

Submit this story to DotNetKicks

Free Image: Bird Over the Waves

From Creative Commons

Submit this story to DotNetKicks

Free Image: Bird on the Sand

From Creative Commons

Submit this story to DotNetKicks

Free Image: Light on the Waves

From Creative Commons

Submit this story to DotNetKicks

Free Image: Bird Tracks in the Sand

From Creative Commons

Submit this story to DotNetKicks

Free Image: Shadows

From Creative Commons

Submit this story to DotNetKicks

Free Image: Mushrooms

From Creative Commons

Submit this story to DotNetKicks

Free Image: Flower

From Creative Commons

Submit this story to DotNetKicks

Free Image: Duck

From Creative Commons

Submit this story to DotNetKicks

PD Photo -- Free Photos And Pictures

Finding images to use in your site is a real pain if you care anything about the photographer's copyright. While looking for a nice picture of a frog I found some sites charging hundreds of dollars for a single image. While I understand that a photographer can spend thousands of dollars on photographic equipment, and they need to eat too, that pricing is way too high for my budget.

Fortunately, there's a great site, PD Photo.org that is a repository of public domain and royalty free images that you can manipulate and use for pretty much anything you want. The only thing they ask is that you verify the license of the photo before you use it, as some of their photo's do have restrictions (which they explain in their FAQ) and to provide a link back to them acknowledging where you found the image.

Well, I found a couple images that I like and am already using one for the header of this blog. Visit their site and check them out.

Submit this story to DotNetKicks

Thursday, April 26, 2007

Night Owl Gene Discovered (Maybe)

The British newspaper Telegraph reports that there may be an "after-hours gene". Basically this gene causes people to fall out of sync with the normal circadian cycle of being alert and awake during light hours and sleeping during darkness.

My wife and I have been night owls our entire lives. I've tried to fight it for years, but within 24 hours of not having to wake at a certain time for work I will lapse into going into a delayed sleeping pattern. And it's not long hours of sleep either, I go to sleep between 2-3 AM and naturally wake around 11 AM. Which puts me around 8-9 hours of sleep. I don't need an alarm clock and my activity level has very little effect. It's been that way for my entire life even during my youth or when I was extremely active and very fit. It's not caused by age or my current, fairly sedentary, lifestyle. My wife is the same, we're just a few hours out of sync I guess. Out of step with the world.

I don't know if I want to be labeled a 'night owl' though, maybe a 'night frog'?

Submit this story to DotNetKicks

.NET Literals Are Implicit Instances.

In .NET literals are really just instances without a name.

Many developers will add extra fields to their code when they simply want to perform an operation on a simple string or numeric literal. This is unnecessary because .NET exposes the same methods from a literal as from an explicit instance field. In .NET literals are implicitly treated as instances.

Arguments about factoring and embedding strings and values in your code aside, this is more about what you *can* do than what the proper way to manage literals is.

When working with a string or numeric literal you don't need to create a new instance field to perform operations on the value. You can call the methods directly because the literal *is* an instance. You can call any non-static method that is exposed by the implicit type of the literal.

For example, you need to compare an unknown value against a constant value that doesn't change. The method could be written as:

/// <summary>

/// Contrived Literals Example 1

/// </summary>

/// <param name="value"></param>

/// <returns></returns>

public bool IsContrivedExample1( int value )

{

    int importantNumber = 1;

    int comparison = importantNumber.CompareTo( value );

    bool result;

    if ( comparison == 0 )

    {

        result = true;

    }

    else

    {

        result = false;

    }

    return result;

}



Some might look at that and not see a problem, and logically, there is no real problem. If it's a method that doesn't get called very often the additional field creation and assignments operations don't matter. The fields are well-named and their roles are clear. But this is an extremely contrived example. Most applications code-bases are generally made up of hundred's or thousands of lines of code, thereby making brevity of code your friend.

Here's an example of using the numeric literal directly to perform the same operations.

/// <summary>

/// Contrived Literals Example 2

/// </summary>

/// <param name="value"></param>

/// <returns></returns>

public bool IsContrivedExample2( int value )

{

    return ( 1.CompareTo( value ) == 0 );

}



We were able to reduce the code by 7 lines (not including braces). Not much in this case, but let's say you have 700 lines of methods like this, you drop about 600 lines of code! Not to mention 3 field creation and 3 assignment operations per method.

Now let's take a look at the resultant IL to see what .NET thinks of the differences in code structure.


.method public hidebysig instance bool IsContrivedExample1(int32 'value') cil managed
{
// Code size 41 (0x29)
.maxstack 2
.locals init ([0] int32 importantNumber,
[1] int32 comparison,
[2] bool result,
[3] bool CS$1$0000,
[4] bool CS$4$0001)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ldloca.s importantNumber
IL_0005: ldarg.1
IL_0006: call instance int32 [mscorlib]System.Int32::CompareTo(int32)
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: ldc.i4.0
IL_000e: ceq
IL_0010: ldc.i4.0
IL_0011: ceq
IL_0013: stloc.s CS$4$0001
IL_0015: ldloc.s CS$4$0001
IL_0017: brtrue.s IL_001f
IL_0019: nop
IL_001a: ldc.i4.1
IL_001b: stloc.2
IL_001c: nop
IL_001d: br.s IL_0023
IL_001f: nop
IL_0020: ldc.i4.0
IL_0021: stloc.2
IL_0022: nop
IL_0023: ldloc.2
IL_0024: stloc.3
IL_0025: br.s IL_0027
IL_0027: ldloc.3
IL_0028: ret
} // end of method LiteralsTest::IsContrivedExample1



.method public hidebysig instance bool IsContrivedExample2(int32 'value') cil managed
{
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] bool CS$1$0000,
[1] int32 CS$0$0001)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.1
IL_0003: ldloca.s CS$0$0001
IL_0005: ldarg.1
IL_0006: call instance int32 [mscorlib]System.Int32::CompareTo(int32)
IL_000b: ldc.i4.0
IL_000c: ceq
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
} // end of method LiteralsTest::IsContrivedExample2


The second example definitely has less overhead. There are less fields being created and loaded and less logical operations.

Let's see what the IL looks like if we replace the integer literal with a constant integer that is declared in the containing class.


.method public hidebysig instance bool IsContrivedExample3(int32 'value') cil managed
{
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] bool CS$1$0000,
[1] int32 CS$0$0001)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.1
IL_0003: ldloca.s CS$0$0001
IL_0005: ldarg.1
IL_0006: call instance int32 [mscorlib]System.Int32::CompareTo(int32)
IL_000b: ldc.i4.0
IL_000c: ceq
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
} // end of method LiteralsTest::IsContrivedExample3


Hmm, aside from the method name, the IL is exactly identical. It appears that there is no penalty for embedding a literal in our method nor is there a benefit for using a constant.

I used to be a steadfast believer in placing *all* my literals in constant fields. Unless the field needs to be reused elsewhere, keeping literals with the methods that utilize them, along with judicious commenting, will keep my code-base cleaner and easier to manage.

Using literals in your code is up to your discretion and coding standards. I hope that you were able to use this article to expand your .NET coding repertoire.

Below is a class containing several examples of calling instance methods directly against string and integer literals.

public class LiteralsTest

{

    private const int ContrivedValue = 1;

 

    /// <summary>

    /// Contrived Literals Example 1

    /// </summary>

    /// <param name="value"></param>

    /// <returns></returns>

    public bool IsContrivedExample1( int value )

    {

        int importantNumber = 1;

        int comparison = importantNumber.CompareTo( value );

        bool result;

        if ( comparison == 0 )

        {

            result = true;

        }

        else

        {

            result = false;

        }

        return result;

    }

 

    /// <summary>

    /// Contrived Literals Example 2

    /// </summary>

    /// <param name="value"></param>

    /// <returns></returns>

    public bool IsContrivedExample2( int value )

    {

        return ( 1.CompareTo( value ) == 0 );

    }

 

    /// <summary>

    /// Contrived Literals Example 3

    /// </summary>

    /// <param name="value"></param>

    /// <returns></returns>

    public bool IsContrivedExample3( int value )

    {

        return ( ContrivedValue.CompareTo( value ) == 0 );

    }

 

    /// <summary>

    /// Tests the string literals.

    /// </summary>

    public void TestStringLiterals()

    {

        System.Console.Out.WriteLine( "Testing String Literals" );

        System.Console.Out.WriteLine( "fizz".CompareTo( "buzz" ) );

        System.Console.Out.WriteLine( "fizz".CompareTo( "fizz" ) );

        System.Console.Out.WriteLine( "buzz".CompareTo( "fizz" ) );

        System.Console.Out.WriteLine( "TypeCode: {0}", "fizz".GetTypeCode() );

        System.Console.Out.WriteLine( "Type: {0}", "fizz".GetType() );

        System.Console.Out.WriteLine( "HashCode: {0}", "fizz".GetHashCode() );

        System.Console.Out.WriteLine( "fizz".Equals( "buzz" ) );

        System.Console.Out.WriteLine( "fizz".Equals( "fizz" ) );

        System.Console.Out.WriteLine( "buzz".Equals( "fizz" ) );

        System.Console.Out.WriteLine( "fizz".Length );

        System.Console.Out.WriteLine( "Character at index 0: {0}", "fizz"[ 0 ] ); //wha, wha, what? ;-)

        System.Console.Out.WriteLine( "Clone(): {0}", "fizz".Clone() );

        System.Console.Out.WriteLine( "Contains(\"iz\"): {0}", "fizz".Contains( "iz" ) );

        // We are replacing the "working" variable with the string literal value.

        // It's a bit of a contrived example, but the method works.

        char[] working = new char[] {'b', 'u', 'z', 'z'};

        "fizz".CopyTo( 0, working, 0, 4 );

        System.Console.Out.WriteLine( working );

    }

 

    /// <summary>

    /// Tests the integer literals.

    /// </summary>

    public void TestIntegerLiterals()

    {

        System.Console.Out.WriteLine( "Testing Integer Literals" );

        System.Console.Out.WriteLine( 1.CompareTo( 0 ) );

        System.Console.Out.WriteLine( 1.CompareTo( 1 ) );

        System.Console.Out.WriteLine( 0.CompareTo( 1 ) );

        // Cannot implicitly convert type 'int' to 'string'.

        string x = 1.ToString();

        System.Console.Out.WriteLine( "ToString(): {0}", x );

        System.Console.Out.WriteLine( "TypeCode: {0}", 1.GetTypeCode() );

        System.Console.Out.WriteLine( "Type: {0}", 1.GetType() );

        System.Console.Out.WriteLine( "HashCode: {0}", 1.GetHashCode() );

        System.Console.Out.WriteLine( 1.Equals( 0 ) );

        System.Console.Out.WriteLine( 1.Equals( 1 ) );

        System.Console.Out.WriteLine( 0.Equals( 1 ) );

    }

 

    /// <summary>

    /// Runs the tests.

    /// </summary>

    public void RunTests()

    {

        TestStringLiterals();

        System.Console.Out.WriteLine();

        TestIntegerLiterals();

    }

}

Submit this story to DotNetKicks

Winamp in a Window

Unify your Winamp UI with the Winamp Single GUI skin.

Winamp is one of the most popular 3rd party media players for Windows. With excellent integrated support for a huge variety of codecs, excellent media management capabilities, and simple streaming media navigation it is one of my first installations when I setup a clean system. Although, I prefer Media Player for watching video, I exclusively use Winamp for audio. One of the features that has always set Winamp apart from its competition is it's well established skinning capabilities. There are probably thousands of skins available for Winamp that can satisfy any computer users aesthetic sensibilities.

I think that I have tried every variation of these skins at some point over the past couple years, to varying levels of satisfaction but have always returned to the default Modern skin that ships with Winamp. It's has a solid feel to it and is easy to navigate, with medium sized buttons that are easy to read and logically laid out. Unfortunately, the one thing that I never liked about any of the Winamp skins was that all the sections of the UI are seperate, albeit dockable, windows. The player, library, play list, equalizer, now playing and video are all seperate windows that can float around your screen.

Enter the Winamp Single GUI skin which uses the Modern skin as it's default look but combines all the major elements into one simple to navigate window.

Screenshot of the Winamp Single GUI skin

Download it and give it shot. Personally, I think Winamp should ship this as one of their default skin options.

Submit this story to DotNetKicks

Doodle Code With Snippet Compiler

Snippet Compiler

Have you ever wanted to test out an idea for a bit of code that is too small to bother with creating a solution for?

Snippet Compiler is a light-weight IDE for the .NET Framework. It has a text-editor that supports some intellisense and code folding. You can build directly from the tool and receive error messages from the compiler in a VS.Net-like Errors tab. Overall, if you have any experience working in the VS.Net environment then you will immediately be able to use plumb the depths of this tool in a few minutes. It's very slick and easy to use. I've personally used it many times over the past couple years whenever I wanted to try out a snippet of code or doodle something to see if it worked before I added it into my working codebase.

Submit this story to DotNetKicks

Robot Chicken: Jedi Bush


Heh heh heh, taco's rule.

Submit this story to DotNetKicks

Robot Chicken: Empire Strikes Back

Submit this story to DotNetKicks

Robot Chicken: Darth Vader Calls The Emperor.


Go for papa Palpatine.

Submit this story to DotNetKicks

Wednesday, April 25, 2007

Vista: Google Edition, or Yahoo! Edition, or ???

One of the weaknesses of the fragmentation of Linux into a google of different and competing versions has been confusion on exactly which distro is the "One True Way".

Linux distro timeline.


As of early 2007 there are about 62 different versions of Linux available. And those are just the bigger fish in the pond. I'm all about exposing myself to new and different ways of doing things but that's just ridiculous. I've played with distros by Red Hat, Ubuntu, Mandrake, Debian, Slackware, and LFS over the years and they've all made me want to punch myself in the face. And no, it's not (just) because I am a Windows Weenie unable to handle anything without a graphical interface, but mostly because each version had significantly different ways of doing things. The distros could even change drastically between releases. Directories would be organized differently, installations would use different formats, some OSS zealot on the distro team would remove some critical (IMO) codec’s, etc.

The problem is not that there are different distributions, but that they differentiate on insignificant details. Only Knoppix has differentiated by enabling developers to create custom tailored distro's that can be pre-equiped with all the software for a specific use. Lisp Knoppix, Monoppix, Games Knoppix, MythTV Knoppix, etc. The value to be found here is a common foundation already set up with the basic software to do what the user wants to do.

When I install Lisp Knoppix or Monoppix distro they are fundamentally the same as far as the base installation goes. The directory structure is the same; the fundamentals are all in place. I didn’t need to spend any additional time figuring out which installation management system to use, one Knoppix system is the same as another except for what matters to me, the user software.

This is where Microsoft could benefit. They have *the* industry standard for stable structures. When you install any version of a Microsoft OS, there is a C: drive. I can't even recall a time before there was a "Program Files" directory. The shell and API are consistent. (PowerShell is going to fix the problem of the current extremely limited console of Windows.) The Windows updater is about the simplest and cleanest installer known to man (IMO).

While Linux is fragmenting because of competition between vendors, Microsoft is fragmenting from within. Microsoft has been slowly declining in the clarity of their basic vision of a fundamental Windows OS since Windows 2000. Their releases have steadily been getting more and more cryptic. Windows 2000 was as clear as one could get, no "Home", "Professional" or "Media Center". Just "Workstation" and "Server", nice, “Advanced” server doesn’t count here. With Vista we get "Ultimate", "Home Premium", "Home Basic", "Business", "Enterprise". Well, that cleared things up. Microsoft is doing the opposite of Linux, they are fragmenting themselves.

So close yet so far away. Windows XP Starter Edition was a forced and seemingly half-hearted response by Microsoft to comply with the EU requirement to provide a minimal XP release. Yet it’s very restricted and limited as to be useless as a base platform for developing custom releases.

To prove that larger corporations don’t always learn from their mistakes, enter Vista Starter Edition. Basically it’s the same stupid decisions on hardware and concurrent application restrictions as they made with the XP version.

Why not remove the restrictions and open the license so that third-party vendors can re-distribute their own version of Vista? It can’t dilute the brand anymore than Microsoft has done to their self. And it would shut up the EU and anti-monopoly zealots by enabling ISVs to bundle their software for re-sale to end-users while still providing a revenue model to Microsoft.

Make Vista a PLATFORM for ISVs. Don’t release multiple versions of Vista, sell one base version with additional extension packs, ala the Plus! SuperPack.

I can almost imagine that glorious day. I boot my Google Vista workstation for the first time. Log in; see that I have a few new GMail messages. Launch Firefox and see my bookmarks are all synced and ready to click. Open Picasa and see my wife’s pictures loaded and ready to upload to Flickr.

Ahh, maybe someday.

Submit this story to DotNetKicks

Tuesday, April 24, 2007

90 Days W/O Computer Games.

World of Warcraft has ruined my life.

Actually, it hasn't but I have to blame someone else for wasting so much time on something that I knew full-well when I started had no intrinsic value.

No World of Warcraft.
No StarCraft.
No Warcraft.
No Guild Wars.
No Unreal.
No computer games.

Playing games in a social context will be permissible. For example, playing Nintendo with family or X-Box with friends.

The point is to break the chain of time sinks that are most modern computer games.


This is the promise I made to my wife and myself. I don't feel like my playing habits had a negative effect, yet. But I looked at the staggering number of hours I had spent in Azeroth and I knew I had to change something.

My abstinence begins today April 24th, 2007 and ends July 24th, 2007.

Wish me luck.

Submit this story to DotNetKicks

PowerShell and I just took our first steps towards what looks like a beautiful friendship.

I've been called a "Tools Guy". Not my words. I’m pretty sure it wasn’t a conspiracy either.

My best guess is that because I am fairly lazy, as I believe all good software developers should strive to be, and am not in the business of making work more difficult for myself; I'm always be looking for ways to off-load my efforts to the computer. That's why I check out different IDEs and databases and Nth generation languages to make it easier for me to do fun stuff with computer, and the less-fun stuff for the people who pay me. Long ago I learned that tools can help me to continue to be lazy. But to truly reap the benefit's of long term laziness I have to put in a little bit of work up front. So I invest time in playing with as many software tools as possible hoping to find a gem that can. Since I share this information with my fellow developers I guess I picked up the reputation along the way. It’s a bit ironic that ones laziness can lead to getting called anything other than unemployed.

Why would a lazy sod like me think that something named PowerShell could be friends? PowerShell sounds so dynamic and important. I mean, the tool has to be important, they didn’t put the word ‘power’ in there by accident, I think.

It all started back when PowerShell had the nonsense name Monad. That doesn’t even mean anything; much less give you a sense of authority. Maybe that’s it, like giving a bouncer a name like ‘Tiny’. Any road, I downloaded Monad and was immediately overwhelmed with a bunch of non-fun things that people were paying me to do, so I ignored it. Beside that it had a stupid name.

Several months later Microsoft officially released Monad with a much more important sounding name and I continued to ignore it, but the blogs were buzzing. Although I download and install it regardless, my packrat side is in constant battle with my lazy side.

Then today, I just need to do something very, very tiny. I need to quickly add dates together for a schedule I am planning. Normally I would just crack open Excel and throw a simple SUM() method into the first field, get my value, close Excel and move on.

=SUM(NOW(),90)

But that was too boring; I have a tool that I hadn’t played with. That situation needed to be rectified. I cracked open PowerShell, and having read someplace that it uses .NET as it’s underlying API I typed the C# call for the AddDays method.

Windows PowerShell
Copyright (C) 2006 Microsoft Corporation. All rights reserved.

PS X:\Home\mhall> System.DateTime.Now.AddDays(90)
The term 'System.DateTime.Now.AddDays' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.
At line:1 char:28
+ System.DateTime.Now.AddDays( <<<< 90)
PS X:\Home\mhall>

Hmm, that wasn't my desired result. Fortunately, it looks cool, and I was in a curious mood so I investigated. By 'investigated' I Google'd for the answer.

The Wonders of Date Math using Windows Powershell

That looked promising.

Apparently, PowerShell has a very different syntax that looks something like C# beat up Ruby and took its lunch money. But that’s okay; Ruby is been getting a bit uppity lately. Now we are cooking with PowerShell.

Windows PowerShell
Copyright (C) 2006 Microsoft Corporation. All rights reserved.

PS X:\Home\mhall> [System.DateTime]::Now.AddDays(90)

Monday, July 23, 2007 8:24:48 PM


PS X:\Home\mhall>

With a little bit of new syntax and a new tool I knocked 3 steps out of what was already a simple process. I love tools that make things easier.

One more tool in my belt, but this one will take me a while before I feel comfortable telling anybody about. No good talking about tools that you haven’t fully mastered.

Uhm, yeah. Nevermind.

Submit this story to DotNetKicks

Fun with Explorer Toolbar development.

When the component is built and registered Explorer seems to be caching the component somewhere and does not replace the component despite the previous version being unregistered.

The only way I've been able to get around this is to manually kill the running "explorer.exe" process and restart a new Explorer session.

After building the Explorer bar project, bring up the Windows Task Manager using the Ctrl+Shift+Esc chord. Then under the Processes tab find "explorer.exe", right click and select "End Process". Your running VS.Net process should not be affected, but your taskbar will noticeably disappear. To resurrect Explorer, use the Alt+F, N chord to bring up the New Task dialog. Simply enter "explorer", without the quotes, then click OK. Your taskbar will reappear and your Explorer bar should be using the correct version.

I like to think that there is a better way to do this.

"A good plan executed today is better than a perfect plan executed at some indefinite point in the future."

- General George Patton Jr

Submit this story to DotNetKicks

Monday, April 23, 2007

NASA Sun Earth Media Viewer

Daily updated images of our celestial center, Sol. Click on an image under the Images tab and then download the full-size image. Use the CANOPUS image as a wallpaper and pretend that you are on one of those sci-fi shows.

"Captain, CANOPUS is reporting abnormal energy fluctuations. We need to reverse the polarity."

Submit this story to DotNetKicks

Fun with COM Interop.

The joy of registering .NET components for COM Interop is a most masochistic delight.

I am creating an Explorer extension for filtering the displayed files and folders to user-specified criteria. Basically, I want a simple Explorer bar not unlike the Google or Yahoo! or the myriad of other tool bar vendors. I am calling the tool, ExplorerFilterBar. Clever, huh?

After no small amount of cursing, here are the steps I took to get my toolbar running. Not working, just running. :-)

I begin by creating my ExplorerFilterBar C# Library project. I will eventually set it up for COM Interop and other stuff but we will get back to that.

My jumping off point is using the BandObjectLib, created by Pavel Zolnikov on CodeProject.com, for the basis of the Explorer Band. The only changes I made to the source were to recompile the application in .NET 2.0. The original source for the base band object can be found here: Extending Explorer with Band Objects using .NET and Windows Forms.

To use the BandObjectLib in my shell application I have to register it for COM Interop. I did this by copying the BandObjectLib.dll to a new folder and registering and creating a new type library.


C:\Program Files\BandObjectLib\bin>regasm /tlb BandObjectLib.dll
Microsoft (R) .NET Framework Assembly Registration Utility 2.0.50727.1318
Copyright (C) Microsoft Corporation 1998-2004. All rights reserved.

Types registered successfully
Assembly exported to 'C:\Program Files\BandObjectLib\bin\BandObjectLib.tlb', and the type library was registered successfully

C:\Program Files\BandObjectLib\bin>


Now we have a registered COM component that I will be able to extend to create Explorer bars. I can verify that the COM wrapper has been created by checking the references dialog and looking for "BandObjectLib". If it's there you are in good shape, if not, close VS.Net and then try again.

To begin creating my new toolbar I need to add a reference to the BandObjectLib.dll that I just registered with COM.

With my new reference I can create a new UserControl so I have a designer window for my toolbar.



using System.Runtime.InteropServices;

using BandObjectLib;

 

namespace FrogsBrain.ExplorerFilterBar

{

    [Guid( "29CF65E4-A7F8-4352-B55A-7EE413A64743" )]

    [BandObject( "Explorer Filter Bar", BandObjectStyle.Horizontal | BandObjectStyle.ExplorerToolbar | BandObjectStyle.TaskbarToolBar, HelpText = "Filter the contents of the Explorer window." )]

    public partial class ExplorerFilterBarControl : BandObject

    {

        /// <summary>

        /// Initializes a new instance of the <see cref="ExplorerFilterBarControl"/> class.

        /// </summary>

        public ExplorerFilterBarControl()

        {

            InitializeComponent();

        }

    }

}




Drag a button onto the form designed and set its Dock property to "Fill". You can delete it later, it's just for demonstration.

Now you are ready to setup for project for COM Interop.

The changes we are about to make have to be applied for the "Debug" and "Release" builds, so set your Project Property Configuration to "All Configurations".

Under the "Application" tab, click the button "Assembly Information". In the dialog box that is displayed check the "Make assembly COM-Visible". Then click "OK".

Create a strong name key file for the project.

Set the project to register and GAC your DLL. Add the following "Post Build" event. Obviously you will need to update the paths as appropriate for your configuration.


cd "$(TargetDir)"
"c:\windows\microsoft.net\framework\v2.0.50727\regasm.exe" /u $(TargetFileName)
"c:\program files\microsoft visual studio 8\sdk\v2.0\bin\gacutil.exe" /uf $(TargetName)
"c:\program files\microsoft visual studio 8\sdk\v2.0\bin\gacutil.exe" /if $(TargetFileName)
"c:\windows\microsoft.net\framework\v2.0.50727\regasm.exe" $(TargetFileName)


Under the Build tab, check the "Register for COM interop" box.

And for the last property dialog change, set the start action under the Debug tab to launch the Window's Explorer when you start the debugger.

The final step to setting up your DLL for COM Interop is the manually open your AssemblyInfo.cs file and set the ComVisible attribute to True.



    1 // Setting ComVisible to false makes the types in this assembly not visible

    2 // to COM components.  If you need to access a type in this assembly from

    3 // COM, set the ComVisible attribute to true on that type.

    4 

    5 [assembly : ComVisible( true )]




Now you should be able to run your application. Watch the Output window to see if any error messages are being generated by the RegAsm or GacUtil utilities, this will help with determining what problems occurred if the application won't build.

If everything went well you should be staring at a default Explorer window. You should now see a new option when you add a tool bar containing the name entered for the toolbar.

Submit this story to DotNetKicks