Monday, August 17, 2009

How is this possible ?

OK, so I have a media player control in my WPF app. For reasons that I cannot fathom, WPF does not let me easily find out the native size of a video, so I have added a map of video paths to sizes. I have built this map, and when I load a video, I grab a screenshot of the first frame. After that, you can play and pause the video, when you pause, it goes to the static screenshot, so that it will appear in screen grabs, which we print and email.

if (MediaAccessManager.Instance.VideoSizeMap.ContainsKey(srcPath))

This is the line of code I use to check if I have a size for this video in my map ( users can import their own videos and then I need to just use DirectX via a third party dll to find the size. I don't do this for my own videos, because sometimes the size reported, is incorrect. Here is the issue. The first time this code runs, I get an exception, stating that the key in question already exists in the collection. Believe me, I have read this code over and over, there is NO code here to put anything into the collection, nor does this crash after the first time. The only possible reason I can think of, is that perhaps the collection does not blow up when I put in a duplicate key, it blows up the first time I try to access it after the fact. However, I call ContainsKey before adding each item, and I have written some code to further confirm that I have no duplicate keys. I also wrote code to deliberately add the same key twice, and it threw an exception at the point of adding the item, as you'd expect.

I really don't have time to debug this, so I've added the block of code above in it's own try/catch. The first time this runs, it throws an exception, but then it does it again right away, and the second time it works fine, causing my code to work perfectly. It's just not at all pretty.

Sunday, August 9, 2009

Why can't I drag and drop a csproj file ?

I was reminded again today that if I drag and drop a sln or csproj file onto the main window of VS2008, I get a message box saying that I am not allowed to do that.  It doesn 't even open File/Open for me, just tells me I need to do it.  Why ? I can't think of any reason for them to insert a message box instead of a jump to the code that opens a project ( with a prompt if they would feel better that way ).  Whose smart idea was that ? It's just a pain.

Wednesday, August 5, 2009

Path.Combine is essentially useless

One of the great things about .NET, coming from C++, is all the stuff that is built in.  Need to send an email ? Sure thing.  Want to use regular expressions ? Go for it.  It took me a while to learn that things I expected to write in C++, I could look for in the library and often find there already.

The System.IO namespace has a Path class, which is used to manipulate file paths.  Things like 'GetFileNameWithoutExtension' are very, very useful.  Some things are a little counter intuitive, such as Path.GetDirectory walking up the directory tree if the string you have is a directory already, but overall, it saves a lot of work.

One of the things I use the most, is Path.Combine, which takes two fragments and merges them to make a path.  In the past, I'd be checking if one string had a trailing slash, if the other had a leading slash, etc.  Path.Combine takes care of that for you.  Right ? Not quite.

There's a couple of quirks here.  To illustrate, the following table has three columns.  The first two are the arguments passed into Path.Combine, the third is the result.


c:\path\dir\file.txtc:\path\dir\file.txt
c:\path\\dir\file.txt\dir\file.txt
c:\pathdir\file.txtc:\path\dir\file.txt
c:\path\dir\file.txt\dir\file.txt
c:dir\file.txtc:dir\file.txt
c:\dir\file.txt\dir\file.txt

The first thing to notice, is that if the second string starts with a \, then you get the second string back verbatim.  This is the issue that hit me in the past.  I assumed that this method existed so no matter what slashes happened to be in the two strings, they would get joined into a single path.  As you can see, this is not so.  Now, I assume there's a specific case for which this behaviour is desirable, but it's not the most obvious one to me, and if there's a reason for it, surely the method could have an overload, or better yet, a method called something in line with the reasoning for not combining these two strings could exist ( a method called Combine, is one I call to combine strings, not to SOMETIMES Combine them ).

The second one is more interesting.  If my first string is a drive letter, with no slash in it, then no slash is added.  I just did a test, I have a file called c:\procs.txt.  File.Exists (@"c:procs.txt") returns false, File.Exists(@"c:\procs.txt") returns true.  So, it seems to me that the slash is needed, but Path.Combine does not add it.  

Overall, this method is basically broken as far as I am concerned, and I have rolled my own version to use instead.  It basically makes sure the first string has a \ at the end, the second doesn't have one at the start, then calls Path.Combine, just out of spite ( given that at this point I could just concatenate the two strings and be done with it )