Saturday, June 8, 2013

Visual Studio 2010 Hangs When Importing Settings

I was having a problem tonight with Visual Studio hanging when I tried to import a .vssettings file. I noticed that if I logged in as a different user it imported OK.

There are two command line flags for VS available to help with an issue like this.

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE>devenv /resetuserdata
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE>devenv /resetsettings

/resetsettings worked for me. FYI I'm running Windows 8.

Saturday, January 12, 2013

Shading Style in RichTextBox 5.0

I am extending the RichEdit 5.0 control in a C# application that I am writing and was playing with using paragraph shading. There are several issues with this. The .NET 4.x RichTextBox control does not expose properties for accessing shading, though the underlying Win32 control does. If we use Win32 messages we can get and set the shading properties. That is enough work on its own, but the second problem we have is that the documentation is not so great. The PARAFORMAT2 documentation lists the various settings for the wShadingStyle member, but they seem to be inaccurate and difficult to visualize what the shading patterns look like. The third problem is that the control itself generates and honors the correct RTF for shading but does not actually display it (as of this writing), though the RTF text can be pasted into MS Word or loaded via RTF and the shading does display.

Shading with the RichTextBox control is not fully baked yet, but I am assuming future controls will fully implement it. You may find the following diagram that describes the settings helpful for PARAFORMAT2.wShadingStyle. Please note that these do not match the values shown in the documentation referenced above.


Wednesday, January 11, 2012

Define Catastrophic

Got this error in Visual Studio 2010 today:

Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))

In reality, I just tried to open a really big file, too big for memory apparently. Hardly a catastrophe. A simple Out of Memory error would have been good.

Thursday, January 5, 2012

Bachianas Americanas

Wow do I love this suite. Happened across John Hall's website this afternoon. John's tone is exquisite. Alas, my genetics gave me thin fingernails. I will never get that tone, I don't think.

Saturday, December 31, 2011

ILSpy

I recently made the switch from .NET Reflector to ILSpy. As of this writing, ILSpy is at v1.0. The biggest drawback to me is the lack of Visual Studio integration and the lack of being able to specify an assembly on the command line. They have good plans for v2.0 so I'm anxious to see that release.

The download for ILSpy 1.0 is just a zip file with the binaries in it. You will have to copy them where you want them to be installed and create your own menu shortcut to it.

To install it as a tool in Visual Studio 2010, select the Tools / External Tools... menu item.

On the External Tools dialog box that opens, press the Add button to create a new tool.

Give it whatever title you want it to have in VS, and tell VS where it is located.
Now ILSpy will be on the Tools menu.

Thursday, December 29, 2011

Tact Filters

Here's a good explanation of how techies and nontechies process information when talking to each other. I know that sometimes I can come across as abrupt. Really, it is just that I am very to-the-point. If you want to lose me in a conversation, then ramble on and on and beat around the bush. A much better way to communicate with me is to say what you mean directly. I take it as information rather than personal attack. On the other hand, most people I meet on a daily basis do NOT operate that way and feelings do get hurt sometimes. Totally unintentional on my part.
"All people have a "tact filter", which applies tact in one direction to everything that passes through it. Most "normal people" have the tact filter positioned to apply tact in the outgoing direction. Thus whatever normal people say gets the appropriate amount of tact applied to it before they say it. This is because when they were growing up, their parents continually drilled into their heads statements like, "If you can't say something nice, don't say anything at all!"

"Nerds," on the other hand, have their tact filter positioned to apply tact in the incoming direction. Thus, whatever anyone says to them gets the appropriate amount of tact added when they hear it. This is because when nerds were growing up, they continually got picked on, and their parents continually drilled into their heads statements like, "They're just saying those mean things because they're jealous. They don't really mean it."

When normal people talk to each other, both people usually apply the appropriate amount of tact to everything they say, and no one's feelings get hurt. When nerds talk to each other, both people usually apply the appropriate amount of tact to everything they hear, and no one's feelings get hurt. However, when normal people talk to nerds, the nerds often get frustrated because the normal people seem to be dodging the real issues and not saying what they really mean. Worse yet, when nerds talk to normal people, the normal people's feelings often get hurt because the nerds don't apply tact, assuming the normal person will take their blunt statements and apply whatever tact is necessary.

So, nerds need to understand that normal people have to apply tact to everything they say; they become really uncomfortable if they can't do this. Normal people need to understand that despite the fact that nerds are usually tactless, things they say are almost never meant personally and shouldn't be taken that way. Both types of people need to be extra patient when dealing with someone whose tact filter is backwards relative to their own."

Credit to Jeff Bigler.

Wednesday, October 19, 2011

Email from Wells Fargo

Well this email from Wells Fargo caught me by surprise.  I had to do a double take until I finally realized it was a scam email.  We call it a phishing attack.  It is made to look legitimate. We have in fact been legitimately notified before by businesses that they've been hacked.  The bad grammar and misspellings should be a warning, but if an an unsuspecting recipient clicks the link, they are taken to a webpage that looks just like the Wells Fargo website, only it's not. 


I was sure it was a scam so I did a tracert on www_online-protection_net to see what was there.  The big red flag was that it traced back to Yahoo's servers.



Next, I did a whois and found out that the site is owned by someone in Italy.


This hardly seems like Wells Fargo.  Last, I went to the website to take a look at it.



It is a very convincing fake of the real site.  One tip off that it is not legit is that it does not show secure HTTP https in the address bar.  I feel sorry for anyone that actually enters their true login credentials here.  Interestingly, if you click on some of the tabs they do link to the real Wells Fargo website, as shown below.


These scammers are good.  I can only imagine how many technically naive people enter their info here.

Thursday, December 30, 2010

Digital Cable Advisor

This month we finally made the switch at home from analog cable TV to digital cable. I have been using Windows Media Center for years, since the old XP Media Center days, and have really enjoyed watching TV and recording movies to DVD's.

But now we have a new hi-def TV, Blu-ray DVD, streaming Netflix, etc. I took one of our old DVD's recorded from analog cable TV and it looks HORRIBLE on our new TV. So now I'd like to make the switch on our home computer to digital TV.

You can buy a modern PC with a digital TV tuner already installed. But you can also install a digital tuner in an existing computer PROVIDED that it meets the Media Center requirements for a digital tuner.

You MUST run Microsoft's Digital Cable Advisor from within Media Center to enable Media Center's digital cable functionality. See here for more information about it.

Unfortunately for me, our home computer doesn't cut it. While I could buy and install a new graphics card to replace the motherboard's integrated graphics, I only have two DDR memory slots and 2GB is as high as I can go. Maybe it's time to shop for a new motherboard.



SQL Server 2008 R2 Express Repair Problem

Yesterday, I blogged about the DACL problems that I had with my new SQL Server 2008 R2 Express installation. I thought after fixing those problems that everything would be OK. As it turned out, the installation wasn't healthy and I decided to run a Repair on it.

I started the installation again, and chose the Repair option under the Maintenance section. The install ran for awhile but eventually I got an error that said


Error 1316.A network error occurred while attempting to read from the file e:\367ede46587e326a4067cebb84442e\1033_ENU_LP\x64\setup\SSCERuntime_x86-enu.msi

This error ultimately caused the Repair to fail.



Googling this error led to a Microsoft Knowledge Base article indicating that this has been a known problem with SQL Server Repairs since 2009. The gist of it is that there is an .msi file having two different names between the SQL Server install and the Visual Studio 2008 SP1 install. The solution is to uninstall the SQL Server 3.5 Compact Edition, then run the SQL Server Repair, which will also reinstall it again.



After uninstalling the four Compact Edition applications that I highlighted above, I reran the Repair. This time it completed without a problem and my SQL Server runs just fine.



Wednesday, December 29, 2010

SQL Server Setup DACL Problem

Just got done installing SQL Server 2008 R2 Express on my Windows 7 development computer. It was an upgrade to SQL Server 2008 Express that installed with my Visual Studio 2010. At the end of the install, the summary noted that there had been an error.


Setup has detected a non canonical discretionary access control list (DACL) on directory 'C:\Program Files\Microsoft SQL Server\100\COM'. Please verify your security settings and make corrections if needed.
With a little googling I learned that this is repairable from Windows Explorer. Interestingly, the COM directory mentioned in the error message was actually OK, but there were 2 peer directories that did in fact have the DACL problem.

Here is how you can fix it in Windows 7. If you right-click on one of these bad directories to view Properties and try to open the Security tab, you will get the following message:


The permissions on Tools are incorrectly ordered, which may cause some entries to be ineffective.
After closing the dialog, you can press the Edit... button, which requires Administrator credentials.



A similar dialog box as the original message will appear, except this time you will have the opportunity to fix the problem. Press the Reorder button.



This will fix the DACL and take you back to the Properties window.



Friday, November 12, 2010

.NET Reflector Won't Integrate with VS 2008

I'm trying to integrate Red Gate's .NET Reflector v6.5.0.135 into my VS 2008 installation. It's supposed to work but it doesn't allow me to select my VS. Don't know what is up with that yet. When I figure this out I'll post about it. If you have figured this out please leave a comment.

Sunday, May 23, 2010

Ctrl+Click to Follow Link in Visual Studio

Yesterday, I had an accident on my mountain bike and ended up in the ER. Besides cuts and road rash, I also sprained my left shoulder, which is now in a sling. The sprain causes unbearable pain whenever I try to move my left arm. So, I am typing this with only my right hand, a new experience in itself.


I have dusted off an old Visual studio project to play with today. In one of the C# source files, I have a comment with a web link in it to refer to a website with more information.



In order to follow the link, you have to hold the Ctrl key down, then click on the link with your mouse. Go ahead and give that a try, using only your right hand! In all the years I've used VS, I've never considered this a usability issue before.

Someday, I will be healed up. But I won't forget this lesson in usability. Perhaps all software developers should go through an exercise where they are temporarily handicapped in some way and be forced to use their software. Could be enlightening.

Thursday, May 13, 2010

Installation Problem with PerfectDisk 10

While I have been very happy with our Win7 upgrades, I have had a nagging problem with one of my applications on this 64-bit computer, namely, my PerfectDisk 10 defragging software. I have used PerfectDisk for years and really like it. However, when I ran the Win7 installer, PerfectDisk was the only application I had in Vista that it said I had to completely uninstall first. In fact, even after I uninstalled it, the Win7 installer wasn't happy - it even wanted all folders removed in the Program Files folder. So that was fine, I did all that.

After running the upgrade from Vista to Win7, I ran into problems installing PerfectDisk 10.

Error 1402. Could not open key:
UNKNOWN\Components\DF0B6CEA0A4B4AA4E8A0436BEF7EADA3\9DC837B7701D7C84E856E266933AC9D8. Verify that you have sufficient access to that key, or contact your support personnel.



After I fixed this problem, as I explain below, I repeatedly got this error on different subkeys in the Registry. What the key names all had in common was the subkey 9DC837B7701D7C84E856E266933AC9D8, which is the Windows installer Product ID for PerfectDisk.

That UNKNOWN\Components part of the error above is actually the Registry key

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components

and the all of the Components entries are the various EXE's and DLL's it installs with it. For some reason, all of these Components subkeys for PerfectDisk became inaccessible after the Win7 upgrade. What SHOULD have happened was that the PerfectDisk uninstall should have removed these keys. Something went wrong though, of which I was unaware.

Anyway, as I tried to examine this Registry entry above, I was able to look at the

Components\DF0B6CEA0A4B4AA4E8A0436BEF7EADA3

key but not the

Components\DF0B6CEA0A4B4AA4E8A0436BEF7EADA3\9DC837B7701D7C84E856E266933AC9D8

key, even when I was logged in as Administrator.



9DC837B7701D7C84E856E266933AC9D8 cannot be opened. An error is preventing this key from being opened.
Details: Access is denied.

Hmmmm... something is amiss here. When I right-clicked Permissions...



I got this error:



You do not have permission to view the current permission settings for 9DC837B7701D7C84E856E266933AC9D8, but you can make permission changes. Um, OK.

Thankfully, after this error, RegEdit continued on to let me make changes to the permissions. When I got there, this is what it looked like - totally empty.



I tried all kinds of things but RegEdit wouldn't let me apply the changes because I didn't have permission (but could change the permissions, as it already told me earlier).

So I clicked on the Advanced button to look at other properties of this key, and noted that the owner of the key was corrupted. Probably the SID of a former user in Vista that was no longer valid in Win7.



So I clicked on the Adminstrators group to make Administrators the owner of the entry. If you don't see Adminstrators, you can click on the Other users or groups... button and add it manually.

After I clicked OK to go back to the previous dialog, I saw this:



Now that Adminstrators were the owner of the entry, I could add Administrators to the permissions for the key. To do that I clicked the Add... button and entered the Administrators group.



After I clicked OK to get back to the previous dialog, I gave Full Control to the Administrators.



Now, what Windows really wants is that SYSTEM be the owner of the key. Now that Administrators has full ability to update this key, I went back to the Advanced permissions on the key to set the owner again. Note that this two-step sequence is necessary. RegEdit wouldn't let me set SYSTEM as the owner the first time.



Since SYSTEM doesn't show up in the list of users to set the owner to, I had to add it manually. So I clicked the Other users or groups... button and added SYSTEM and pressed OK.



Now SYSTEM was in the list and was the highlighted new owner.



I pressed OK again to get back to the original Permissions dialog, then pressed OK again to close that dialog and get back to the main RegEdit screen. Now when I clicked on the subkey, it displayed as expected.



I had to search Components and repeat this procedure for every occurrence of the subkey 9DC837B7701D7C84E856E266933AC9D8. Hopefully this will help you when you are facing the same trouble.

Monday, May 10, 2010

Windows 7 Upgrades

It's been awhile since I've checked in. Things have been crazy busy at work and at home. Homewise, we are a family with three teenagers. Enough said there. Workwise, our company is weathering the recession just fine, thank you. We have a waiting list for customer installs (and no, we do not produce shrinkwrap software). It's a nice position to be in, of course, but the work pace is relentless.

In the last couple of months I have upgraded all of our home computers to Windows 7. This consisted of upgrading one Vista64 desktop and two WinXP32 laptops. I bought all of the software on eBay in the $50-70 range.

The experience went very well. The only upgrade path for XP computers is to do a fresh install of the OS. This requires all of your software to be reinstalled after the upgrade. But the installer copies all of the current folders into a new folder so there is no need to worry about it wiping the drive or reformatting. All of your files are still there. You would need to watch out, though, if you have data that you will need to export before the upgrade, such as email (including rules!), SQL data, source control, etc. If your data is flat files, no worry, they will be there, otherwise be very careful... Also, if there are multiple user accounts you need to make sure you get all of the data exported for the others, too. The fresh OS upgrade is very quick, since it only installs the OS files and lays down a new Registry. The most work it needs to do is to identify and install drivers needed for your hardware.

On the Vista box, I chose to upgrade it rather than install a fresh OS. It seemed to go OK, but was very slow. I'm talking several hours, like 5 or 6. In retrospect, I would do the fresh install. I am still considering doing that, even now. The reason I didn't is for the reasons I mentioned above: email, SQL data, source control databases, and settings configurations in various applications that would need to be exported and saved.

Overall, I highly recommend Win7 for everyone. It has an outstanding user experience.

For comparisons, here are examples of vanilla Vista and Win7 desktops.



This is an example of the Windows 7 installer screen.

Monday, October 12, 2009

New Gigabit NIC

A couple of weeks ago I installed a new NIC in my aging emachines box. The computer has an integrated 100 mbit NIC on the mobo which has been working just fine, but I have recently been upgrading my equipment to gigabit. My new D-Link DIR-855 Wireless N/gigabit router is the new core of our home network. Our 1 TB Buffalo TeraStation supports 1 gbit links, and now my main computer also does. I really wanted this to speed up my Ghost backups to the TeraStation.

It took a long time for me to decide which NIC to get for my PCI Express mobo. After a bunch of research, I finally decided on the D-Link DGE-560T. There are conflicting reviews out there on its worth, but I decided its cost was low enough that I could afford to take a chance.

Happily, the card has been working well, and after disabling the integrated NIC in the BIOS, it really was plug-n-play, even on this Vista 64 box. I did have one problem after the install, which was that the security rights got screwed up on a Windows system folder. I figured out how to solve that, though, and blogged about it here.

Here's a picture of the NIC. It is very small, smaller than I expected. The card edge occupies just a small portion of the PCI Express slot on the mobo.


Wednesday, September 30, 2009

Finally Figured Out My Vista Problem

Wow I have found the solution to a problem that I have had intermittently since installing Vista 64. Sometimes after upgrading my computer, my VPN connection would become inaccessible and my Ghost service would quit working (see A Painful Lesson and Fragile Vista). Tonight, I got bit by this again after installing a gigabit network card in my computer.

A natural thing to do when you get errors is to go look in the Windows event log to see if there are any messages. But when I tried to open the Event Viewer, I got this message:

Event log service is unavailable. Verify that the service is running.



Well, in fact, the Windows Event Log service was not running, and attempts to start it gave the error:

Error 4201: The instance name passed was not recognized as valid by a WMI data provider

So, I did some Binging and found a tip to check the permissions on the C:\Windows\System32\LogFiles\WMI\RtBackup folder. It didn't look good. They didn't at all match the permissions on its WMI parent folder. What it had was just my user name, and what the parent had were several system accounts.



I removed my account and added the system accounts to match the parent folder.



After rebooting, everything was back to normal again. I have no idea why certain installs mess up the permissions. Hopefully, this will be useful info for someone experiencing this problem.

Tuesday, September 29, 2009

Automating Excel from C# Pt. 1

Recently, I have wanted to convert Excel spreadsheets to CSV files for further processing. Excel provides a COM Automation model for using its functionality from 3rd party applications.

One of the things about COM Automation is that if you don't close all of the handles you are using in the application being automated, orphaned instances can be left running and they will never quit unless you use Task Manager to kill them or reboot the computer.

So, the automating application needs to be very careful to get rid of everything it is referencing in the automated process to allow it to shut down. The problem is, .NET is a garbage-collected environment, and this means that objects are destroyed, or released, whenever the framework decides that memory should be freed up. Unlike C++ destructors, which are always called immediately when a variable goes out of scope or is delete'd, .NET finalizers are called only when the framework wants to free memory. Exactly when that happens cannot be known with certainty. Oh, objects will be released eventually, but not necessarily when the application might like.

Therefore, the .NET framework provides the IDisposable interface, which allows the non-.NET allocated portions of an object to be immediately freed without the .NET portion being freed. This is what we need to use when automating COM so that COM handles are released in a controlled, dependable, and timely fashion.

In the next part to this series, I will talk about the IDisposable interface.

Tuesday, September 22, 2009

Multiple vs. Single Exit Points

Recently in one of the newsgroups a side discussion came up about the benefits of a single exit point from a function. There was a time when I followed that notion very closely. However, I found that the functions ended up having more nesting and other logic to "jump over" code paths once the return value was determined. In recent years I have found myself pretty much ignoring that idea completely.

Here is an example of some actual code I have somewhere. I have removed the null-checks, comments, and other exception throws to get down to the core of the logic.

In this snippet you can see that once the return value is determined, it immediately returns it.

    1 private int CompareTokens(CommandLineParser commandLineParser)
    2 {
    3     var n = System.Math.Min(this.tokens.Length, commandLineParser.tokens.Length);
    4 
    5     for (var i = 0; i < n; i++)
    6     {
    7         var result = this.tokens[i].CompareTo(commandLineParser.tokens[i]);
    8         if (result != 0)
    9         {
   10             return result;
   11         }
   12     }
   13 
   14     if (this.tokens.Length < commandLineParser.tokens.Length)
   15     {
   16         return -1;
   17     }
   18 
   19     if (this.tokens.Length > commandLineParser.tokens.Length)
   20     {
   21         return +1;
   22     }
   23 
   24     return 0;
   25 }

In the next snippet I have refactored the original routine into a single exit point. Note the required variable for the return value in line 3, the break at line 12 and the extra logic at lines 16 and 22 required to jump over the other code paths. Somewhere I know I have a more severe example. I will look for it. In fact, I remember it is an old one that used to have one exit point that I have since converted to multiple.

    1 private int CompareTokens(CommandLineParser commandLineParser)
    2 {
    3     var result = 0;
    4 
    5     var n = System.Math.Min(this.tokens.Length, commandLineParser.tokens.Length);
    6 
    7     for (var i = 0; i < n; i++)
    8     {
    9         result = this.tokens[i].CompareTo(commandLineParser.tokens[i]);
   10         if (result != 0)
   11         {
   12             break;
   13         }
   14     }
   15 
   16     if (result == 0)
   17     {
   18         if (this.tokens.Length < commandLineParser.tokens.Length)
   19         {
   20             result = -1;
   21         }
   22         else if (this.tokens.Length > commandLineParser.tokens.Length)
   23         {
   24             result = +1;
   25         }
   26     }
   27 
   28     return result;
   29 }

So, what's your opinion? I suppose some of you have seen coding horrors where multiple exit points have been abused.

Saturday, September 19, 2009

Consolas Font in Code Snippet Windows

I have the Consolas font issue fixed for my code snippet windows. If you have the Consolas font installed, the snippet windows should now show in that font. I haven't figured out the line ending problem yet, though.

    1 using System;
    2 using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Windows.Forms;
    5 
    6 namespace Test1
    7 {
    8     static class Program
    9     {
   10         /// <summary>
   11         /// The main entry point for the application.
   12         /// </summary>
   13         [STAThread]
   14         static void Main()
   15         {
   16             Application.EnableVisualStyles();
   17             Application.SetCompatibleTextRenderingDefault(false);
   18             Application.Run(new Form1());
   19         }
   20     }
   21 }

The issue with the font was that the  <pre>  tags for the coloring on the fragments weren't inheriting the  font-family:consolas  that was specified in the style for the  <div>. Modifying the Copy Source As HTML utility settings remedied that.

So now my settings for CopyAsHTML are:




Friday, September 18, 2009

Posting Code Snippets to Blogger

I want to be able to post code snippets and I found a little utility that integrates with Visual Studio 2008 called CopySourceAsHtml. This utility lets you select source code in a code window and copy it verbatim to the clipboard, which can then be pasted into the blog.

In this shot, I selected some source code, and right-clicked. I then chose Copy As HTML...



When you do this, the utility's dialog box appears allowing you to choose options. I have set options on two of the tabs.




On the File Style tab, I have added some more style settings for the  <div>  that it creates for the snippet.  The  overflow:auto  setting will add scroll bars as needed, the  white-space:nowrap  setting will turn off word-wrapping, the  height:500px  setting sets the box height to 500 pixels, and the  border:inset silver  sets the box's border style to inset with silver color.

When you press OK the HTML is placed on the clipboard and is ready to paste into the blog post.



For this to work, I also had to make a change to my Blogger template, otherwise the word-wrapping setting was ignored and was always on.



This is the final result:

  296                 else if (path.EndsWith(":"))
  297                 {
  298                     path += @".\";
  299                 }
  300                 else if (!path.EndsWith(@"\"))
  301                 {
  302                     path += @"\";
  303                 }
  304 
  305                 path = System.IO.Path.GetFullPath(path);
  306                 if (path == null)
  307                 {
  308                     throw new System.ApplicationException("GetFullPath() returned NULL unexpectedly.");
  309                 }
  310 
  311                 if (fileType == FileTypes.File)
  312                 {
  313                     // Special cases for when x.txt is truly a FileInfo, this code
  314                     // must come after the GetFullPath() call above:
  315                     //      c:\x.txt\
  316                     //          Path: c:\x.txt\
  317                     //          File: 
  318                     //      c:\x.txt\.
  319                     //          Path: c:\x.txt\
  320                     //          File: .
  321                     //      c:\x.txt\.\.\.\\\.\.\..\x.txt\\\\\.\.\.\..\x.txt\.\
  322                     //          Path: c:\x.txt\
  323                     //          File: 
  324                     //      c:\x.txt\.\.\.\\\.\.\..\x.txt\\\\\.\.\.\..\x.txt\.\.
  325                     //          Path: c:\x.txt\
  326                     //          File: .
  327                     //      c:\x.txt\.\.\.\\\.\.\..\x.txt\\\\\.\.\.\..\x.txt\.\.\\\
  328                     //          Path: c:\x.txt\
  329                     //          File: .
  330                     if (((fileName == string.Empty) || (fileName == ".")) &&
  331                         path.EndsWith(@"\"))
  332                     {
  333                         fileSpec = path.Substring(0, path.Length - 1);  // Make the new filespec be the earlier resolved Path minus the trailing \
  334                         path = System.IO.Path.GetDirectoryName(fileSpec);
  335 
  336                         if (path == null)
  337                         {

One thing I note is that you cannot easily copy text out of this window, because it doesn't have normal line ends. I am looking into how to remedy that. I do plan to post downloadable code when I post snippets. The other thing is that this is displaying with a Courier font, rather than Consolas as in Visual Studio.