Thursday, April 12, 2007

Scott Hanselman recently posted about a bug that can occur when using Firefox as your default browser. The root problem deals with Outlook trying to start up Firefox using DDE instead of just a simple command line argument. At work, we ran into a very similar situation, because we were wanting to open up URLs in the default browser from our application. Normally, this would be easy because all you would have to do is Process.Start the URL without providing an application and ShellExecute would handle the rest for you. Needless to say, this wasn't going to work for us because we had overridden the default open action for URL shortcuts with our own action (it's a long story that I won't go into in this post).

Our solution started with pulling out the default browser from the registry (we still kept the original open action command, see HKEY_CLASSES_ROOT\HTTP\shell\open\command). Once we have the value, we thought we would be able to Process.Start the command line from the registry passing in the specified URL. We tested it out in Firefox and everything worked great. Even better, Firefox would reuse windows based on the user-defined settings.

Not so with Internet Explorer. Internet Explorer would open the URL for us, sure, but it would not respect the user-defined settings on the reuse of windows. This was confusing to us, because Outlook was smart enough to get Internet Explorer to reuse windows. The question was how it was happening... and that's where DDE came in.

When Outlook opens a URL shortcut, it connects to the DDE IExplore server on the WWW_OpenURLNewWindow topic. If he is able to connect, then Internet Explorer is already running. He then sends an XTYP_EXECUTE transaction passing along the URL. If everything works correctly, then Internet Explorer will open the new window and bring it to front for you. If no Internet Explorer instances are running, Outlook will start a new instance.

In case you were wondering, this was all verified using DDESpy (which you can find in the Visual C++ 6.0 Tools installation... if you still have it). It was also tested against Internet Explorer 7 and Outlook 2007 which means this information is still current.

And yet, Raymond Chen has encouraged us to stop using DDE, because "DDE has been dead as a shell interface for over ten years." Oh how I wish that the Internet Explorer team knew that. If they had, we wouldn't have had to code up DDE to get similar behavior in our application. And let me tell you, DDE is not fun to code against. There are very few resources covering DDE on the Internet (probably because DDE died before the Internet became really widespread... or not).

posted on Thursday, April 12, 2007 7:54:14 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Friday, April 06, 2007

I'm sure you've seen this page before:

I've seen a million posts on it, too. Jeff Atwood posted about this problem when he was talking about user-friendly 404 pages. Internet Explorer tries to hide ugly error pages from you unless the page displayed is greater than 512 bytes in size.

I used to have this setting turned off, but my employers recently pushed out Internet Explorer 7 to the corporate masses. I already had it installed, but it apparently went over my previous installation, which means that I lost my previously customized settings. Anyway, I spent about an hour trying to figure out why my IIS installation had CustomErrors turned on for everybody before I realized that it was actually Internet Explorer helping me out.

To turn the setting off, go here:

As Jeff points out, the best solution is to make sure that your error pages are bigger than 512 bytes. Most of the time, ASP.NET error pages are far larger than 512 bytes, too. HOWEVER, error messages from HTTP Remoting* are NOT always greater than 512 bytes and I'm not sure if you can customize those or not. So I like to just save myself the headache and turn this off.

* As a note, a useful tip for debugging HTTP remoting applications is to browse to your registered channel (i.e. http://localhost/remotingEndPoint.rem) with a browser. If there are any problems with your remoting configuration or with your assemblies being loaded, you'll get the friendly ASP.NET error message displayed to you. If you don't get an ASP.NET error, you'll usually get a message that looks like this:

System.Runtime.Remoting.RemotingException: Requested Service not found

It basically means that you're configured correctly and that the server didn't find a service based on your HTTP GET. I prefer checking remoting servers this way because it is easier to read messages in your browser than trying to interpret a binary serialization exception while in your remoting client.

posted on Friday, April 06, 2007 9:31:23 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, April 03, 2007

Read it here:  http://weblogs.asp.net/scottgu/archive/2007/04/03/expression-added-to-msdn.aspx

Woohoo!

This is a great move by Microsoft and I really appreciate it.

I wonder how many other people are firing up their blogs to post this, too.

posted on Tuesday, April 03, 2007 11:51:46 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, March 29, 2007

If you're not already subscribed to Jeremy Miller's blog, do so now. I'll wait for you to come back.

Okay, now that you've done that, read his latest post on sunk costs and architectural decisions. I'll keep waiting.

Done? Good.

As I was reading his post, I found myself nodding my head in agreement over and over again because I've been dealing with the exact same issues at work for the past few months. Sunk costs are something that every business deals with. A sunk cost is when you've already spent money on something and you later wish that you hadn't spent that money. The Wikipedia example that Jeremy cites of going to see a bad movie is the classic example of sunk costs.

One of the biggest problems with sunk costs isn't the actual cost involved but the fact that as soon as you admit you're dealing with a sunk cost, you're also admitting that a bad decision was made somewhere. This can lead to hurt feelings, hurt pride, etc. Jeremy points out that there can be political implications of this as well. Management will not be happy to find out that this awesome tool that was supposed to bring world peace, cure cancer, and solve the energy crisis actually is too slow for the masses to effectively use. They're likely going to question more than just the tool afterwards.

However, I submit that these same sunk costs can provide an incredible benefit to developers. One of the quickest and most efficient ways to learn is to make mistakes. If you get burned badly enough, you're not going to touch the hot stove again, because you now know that it is hot. If you're the one who is responsible for the bug that cost your company thousands or millions of dollars, will you make that same mistake again? Of course not!

Learn from your mistakes! I've been fortunate to be a part of a similar process and the results so far have been very positive. Our team has really come together and pushed out some really good code that our users are very happy with. Prior to starting the rework, we had all been dreading continuing to deal with the prior version of the product, because we knew we would be spending our time hunting down obscure bugs and hearing complaints from users. The question we continually heard from users was, "why is this better than before?" We hated the question because we didn't like the system either! Now, we can tell them with confidence that our work is without a doubt better and that we're behind it 100%.

From the management side, I submit that managers who give their teams a chance to fix mistakes and start over can gain a great deal of respect from their team. Our manager had ties to the prior system, but he also knew there were problems with it. The system had gone through three different groups before we had ever been given responsibility over it! No one even knew the system anymore! Not only did we come together as a team more, we also became more familiar with the code and were able to really take ownership of it. A positive response to problems or mistakes reflects a real maturity in leadership.

You can treat sunk costs as a straight loss and accept defeat. The better alternative is to treat them as a training expense. The benefits from training are not tangible, but most companies still spend money on their employees because they can become more efficient. Similarly, when we respond to sunk costs positively, they can provide the same kind of intangible benefits as training. Mistakes were made, but mistakes are an opportunity for growth. We all write bad code. Just be sure you learn from it and become a better developer!

UPDATE: Some clarification on sunk costs - a reader pointed out that a sunk cost isn't necessarily a bad decision or mistake, just an unrecoverable past expenditure. I'm no economist, but it seems that the term typically carries negative connotations.

posted on Thursday, March 29, 2007 7:39:07 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, March 27, 2007

Lately, I've been working on performance enhancements to one of the projects at work. Our users had all mentioned that the application's startup time was pretty slow and wanted to know if we could do anything to speed it up. Of course, when all of your users have been using green screen applications, even native C applications will likely seem slow to them... but anyway. We started digging in and found a few places where we could optimize our code but our form still took a while to load.

While testing, I happened to have Process Explorer up and noticed that our process was kicking off csc.exe, which is the C# compiler.

This is one of those instances where some (if not all) of you will know what I was seeing here. You see, we were using XML serialization in our project. When you do XML serialization, some code-gen happens to make the serialization magic work. If you have FileMon or ProcMon up, you'll actually see a temporary C# file being written out and compiled. I might have remembered this (Scott Hanselman has a lot of posts on the XmlSerializer) if I had thought about the temp file aspect, but I was wondering more about the C# compiler.

Anyway, the best way to avoid this precompilation step is to do the precompilation yourself using sgen. Basically, if you give it an assembly named Foo.dll, you'll get back an assembly named Foo.XmlSerializers.dll.

My only question regarding sgen is why standard compilation doesn't do this for you automatically. I'm sure there is some reason why, but I haven't thought of it yet. Regardless, I went ahead and added it to our build script and we've seen increased performance.

As a side-note, Red Gate's ANTS Profiler is an awesome profiler tool to help you find bottlenecks in your code. It will put big red lines next to the code that takes a long time to run.

posted on Tuesday, March 27, 2007 6:55:46 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, March 20, 2007

This is completely off-topic, but I thought it was pretty funny.

I had this past Monday off from work and when I got into the office today, I noticed that I had a voicemail. As a programmer, that usually isn't a good sign, because many times it means a user has tried to call to let you know about a problem. When I noticed the message was left on Saturday morning, that made it seem even worse.

Then I actually listened to the message.

"If you would like to accept this call, please press 3... now."

I won't give you the rest of the message. Needless to say, hearing that prerecorded voice telling me my options for a collect call that I wasn't able to accept made me feel much better about my day.

I hope a user wasn't trying to call me collect.

posted on Tuesday, March 20, 2007 6:09:34 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, March 15, 2007

So, want to improve at what you're doing?

In a phrase, don't stop learning.

In my profession (software development), this is even more important, because the field sure isn't going to wait for you. Jeremy Miller posted about how developers need to get out and "see the world." He was specifically talking about checking out other technologies like Ruby because it can help to see how things can be done differently, but he makes one statement that I liked in particular:

Software development is still a young profession that's in a state of constant flux and it's just not smart to put your head in the sand.

...

Yeah, I know, we all want work to end at 5 pm.  But development is the profession we chose, and if constant learning doesn't suit you, it's time to move onto something else.

This reminds me of a phrase that Scott Hanselman used in his recent podcast on "Hiring and Interviewing Engineers." Here's the relevant snippet from the podcast:

Scott Hanselman: ... I also ask
people about what blogs they read, what books
they read, how do they become lifelong
learners
...

Carl Franklin: Yeah, very important.

Scott Hanselman: ...because it is not that you
want them to be people who are necessarily
working on Open Source projects at night, but
they should be enthused; they should be stoked
about whatever they are working on.

I actually typically use my lunch hour to catch up on feeds, which are an excellent source of continuing learning. As far as books... well, I've got like 5 or 6 at home that I need to read. I still need to work on that.

What are your tips on continual learning?

(man, this post reads a lot like those cheesy "the more you know" commercials from TV... sorry...)

posted on Thursday, March 15, 2007 12:36:50 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, March 08, 2007

I'm sure I'm the only one that has ever messed up like this, but anyway...

My TV is one of the 30" HDTV monitors. It was cheaper at the time and the box didn't mention anything about it not being a true "HD" TV. In other words, it doesn't support HD without a tuner. Regardless, though, it was cheap and it has a great picture.

Unfortunately, it doesn't have HDMI input, so when I upgraded from the old HD package from Dish Network to their HD/DVR service, the upgraded receiver I got only had component output and HDMI output.

Big deal, right? Surely I can deal with component.

Except that my Xbox 360 takes up one of my component inputs and my Wii SHOULD take up the other component input. I'm out of component inputs.

I did what any other self-respecting geek would do and headed over to monoprice.com, which is by far the best place to get cables or adapters... period. I ordered an HDMI to DVI converter a few days after ordering my Wii component cables. The Wii cables came first, so my 360 was unhooked for a few days while I could enjoy some 480p Wii goodness (it does look better than the 480i with the prepackaged composite cables by the way).

Today, my HDMI to DVI converter came.

And I goofed up.

I ordered the DVI (male) to HDMI (female) converter.

Not the DVI (female) to HDMI (male) converter.

The plugs don't work that way.

*sigh*

What's even better is I didn't realize this until I had already pulled the TV out, unhooked the satellite receiver from the component and rehooked the 360 component back in.

Moral of the story: double check your cables before you buy new cables.

posted on Thursday, March 08, 2007 6:37:08 PM (Central Standard Time, UTC-06:00)  #    Comments [0]