Wednesday, June 18, 2008

A couple of weeks ago, I was fortunate enough to attend the Tech Ed 2008 Developer conference. It was my first Tech Ed conference and I had a great time. (Yes, I still need to blog about my experiences there overall and I’m still planning on doing that.) One thing I wanted to bring up if you’ve never been to Tech Ed before is the great experience that the Hands on Labs (HOLs) provided. Basically, you walked up to the HOL computer and, in a few short steps, you had a full development virtual machine ready to go. It was a really nice experience and ensured that you could try out new features without having to set up your own VM or worse, download and install a lot of betas on your own development machine.

Apparently, Microsoft is using the same setup over the web. Maybe I’ve been in the dark for a long time, but I’ve never used a VM in a browser window before. Check the screenshot out:

image

Seriously, look at the browser title – this is in IE. On the right side of the screen, you’ve got the lab walkthrough, too. If you’ve been unable to look at new technology like .NET 3.5, LINQ, WPF, WCF, etc, you should check out Microsoft’s Virtual Labs. The MSDN Virtual Labs are at http://msdn.microsoft.com/en-us/virtuallabs/default.aspx, but TechNet also has labs for things like Windows Server 2008.

image

posted on Wednesday, June 18, 2008 7:01:36 AM (Central Standard Time, UTC-06:00)  #    Comments [2]
 Friday, May 23, 2008

Most of the work I currently do (during the day) is with WinForms applications and most of the time, debugging their problems really isn't all that hard. Application hangs or crashes that only occur on one machine at a remote location are not easy though. We ran into one of those situations a few weeks back. I told our support group that if they saw the hang again to let me know and I would swing by so that we could get a memory dump of the application and start debugging it. Here's everything I did to figure out what went wrong.

First thing, install Debugging Tools for Windows. This will get you things like adplus and windbg. Make sure you pick the right version for your platform (i.e. x86 or x64) because the debugger has to match the platform you're debugging on. I already had it installed on my machine, but I shared the directory so that I could access the tools on the remote machine that was having the hang.

Next, I remoted into the machine with the problem and ran adplus to get a memory dump. To do this, I first copied over the debugging directory to the remote machine from my share. Luckily, the Debugging Tools can be copied and therefore don't need an MSI or setup executable. To get the dump, I pulled up a command prompt, moved to the debugging directory, and ran 'adplus -hang -p 3423' where 3423 was the process ID for the application that was hanging. If you're dealing with an application that is crashing, you would need to pass different arguments in. By the way, note that adplus is just a VBScript - this means that you can open it and see what they're doing if you're so inclined. You can get the PID from either task manager or process explorer.

image

Let this script run to completion and it should create the memory dump (in this case, a minidump) in a directory that looks something like this:

image

I then zipped up this directory and copied it back over to my machine so that the user could get back to work :-) Get back to your desk because you'll be able to do everything else there.

This is where it gets fun, because we get to use WinDbg. Before doing any real work with WinDbg, I would strongly recommend getting your colors customized because it is very hard to spot errors or warnings when all the text is black on white. Check out Tess's post on setting up a custom workspace for WinDbg. I set up WinDbg exactly as she did in the post and it works quite well.

Next, you can open your minidump. Under the File menu, there is an "Open Crash Dump" command that you can use (Ctrl+D for you keyboard guys) so pull that up and open your minidump file. It should look something like this:

image

You can think of WinDbg sort of like a command prompt, even though it has windows and buttons. It is just as user friendly as the command prompt is when you're sitting at the C: prompt. In other words, it isn't friendly at all. In this case, instead of a C: prompt, you have the prompt at the bottom of the screen.

WinDbg starts out as an unmanaged/native debugger, which means you could debug your managed application, but it will be fairly difficult with just native commands. What you need to use is a tool called SOS. John Robbin's, master debugging guru guy, has an excellent MSDN Magazine article on SOS that you should read for more information. My next step was to load up the SOS extension in WinDbg by typing '.loadby sos mscorwks' which tells WinDbg to load the SOS extension from the same directory as the mscorwks assembly was loaded from. (check out this comment for cases when the loadby might not work, such as when mscorwks hasn't been loaded yet)

image

When I typed it in, I unfortunately got an error, though (pasted below for Googlibility, if that's a word).

PDB symbol for mscorwks.dll not loaded
Failed to load data access DLL, 0x80004005
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)
            2) the file mscordacwks.dll that matches your version of mscorwks.dll is
                in the version directory
            3) or, if you are debugging a dump file, verify that the file
                mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.
            4) you are debugging on the same architecture as the dump file.
                For example, an IA64 dump file must be debugged on an IA64
                machine.

You can also run the debugger command .cordll to control the debugger's
load of mscordacwks.dll.  .cordll -ve -u -l will do a verbose reload.
If that succeeds, the SOS command should work on retry.

If you are debugging a minidump, you need to make sure that your executable
path is pointing to mscorwks.dll as well.

This got me digging for a while to figure out why I couldn't load up SOS. Quite a few other people were curious, too. The gist of it can be summed up in this Microsoft Connect post, which details that you have to have the exact same version of the .NET Framework as the machine where the minidump was taken. In short, I had installed .NET 3.5 on my machine which included patches to .NET 2.0 while the user who was having the problem was a few versions back.

To confirm this, you can use the loaded modules command (lm) to see all of the modules that were loaded at the time of the minidump. I specifically used 'lmv m mscorwks'. The 'v' apparently means details or something and the 'm mscorwks' tells the command to match on modules named 'mscorwks'. Here is the result, with the file version info from my local mscorwks file as well (found in c:\windows\microsoft.net\framework\v2.0.50727).

image

Don't despair if you're in this situation, because I have a solution. Virtual machines! It takes a bit of work, but you can get a VM set up with the same framework version. I started out with blank Windows XP SP2 VM and installed the .NET Framework 2.0 RTM on it. Turns out, I was still off. The below screenshot is from the VM.

image

I was starting to get frustrated at this point, but Doug Stewart saved the day with a couple of posts on .NET 2.0 versions, one on .NET 2.0 revisions and one on the version history of the CLR 2.0. I was able to determine that the problem computer was running a patch from KB928365. I installed the patch on the VM and... SUCCESS! SOS loaded up!

With SOS loaded, you run a lot more interesting and powerful commands from WinDbg, like !threads, !CLRStack, !analyze and more. Here are the basic steps I took to attempt to narrow down what was going on.

I ran !threads, which displayed all of the threads that were running at the time the minidump was taken.

image

You can see that, though it looks like a lot was going on, there really was the main STA thread (the thread that contains the WndProc which pumps the Windows messages) and a lot of system threads like the Finalizer threads and Completion Port threads.

You can switch between threads, by using the ~[THREAD]s command, like ~11s, which switches to the thread with the ID of 11. Once switched to a thread, you can run !clrstack and get the call stack for that thread.

image

It looks like thread 11 was an animation timer. Back on the main thread (STA), it really just looks like normal WndProc activity - nothing too strange.

image

It was looking like I wasn't getting anywhere, so I decided to try something else. I ran the DumpStackObjects (!dso) command, which gives me all of the object instances on the stack.

image

Looks like the application in question was using an Infragistics library, but the thing I was really interested in was the bottom one, the WinFormsAppContext, which was an instance of an ApplicationContext. From that instance, I could run the !do (dump object) command to see details about it.

image

From there, I wanted to find which mainForm it was using. I ran !do on the Value column of the mainForm instance.

image

Nice! Now I know the name of the instance that was loaded! At this point, I've got a much better idea about what is going on and can now start digging through some code to try to determine what it is doing.

The rest of the story is fairly boring because, after opening the offending code, I spotted the problem fairly quickly. The hang, if you even want to call it that, had nothing to do with threading. It just looked like the application was hanging because, in the Form's Closing event, the application in question was cancelling the close and hiding itself. I have no idea why, but I guess that's debugging for you.

To finish off, I'd like to share some excellent debugging resources, particularly with WinDbg.

Hope this helps!

posted on Friday, May 23, 2008 8:57:15 AM (Central Standard Time, UTC-06:00)  #    Comments [3]
 Wednesday, May 21, 2008

I've been meaning to get a local version of my blog running so that I could test changes and tweaks to my theme and I finally found some time yesterday to do that. Can you tell the difference? Basically, I added the social networking links on the right as well as the Tech Ed 2008 badge.

Tech Ed 2008 - Meet Me There

This will be my first time to go to Tech Ed, so I'm excited. I've only been to one other conference and that was devLink last year (which was awesome - I still need to register for this year!). There will be 3 other guys from my company going and I know that Randy Walker and I think Jay Smith will be as well. Anyone else out there going? Let me know in the comments! Also, anyone planning to attend Party with Palermo? I haven't registered yet, but I'm thinking about it.

Speaking of conferences, the Northwest Arkansas area is planning a technology summit. I've missed out on the discussions about it so far but I'm hoping to make the next meeting to talk about it. We'll make sure information gets out regarding the specifics so that everyone can participate.

posted on Wednesday, May 21, 2008 7:18:48 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Wednesday, May 07, 2008

A coworker swung by a few days ago to ask some questions about using Reflection. I learn really well by example so I decided to use Powershell to show using Reflection. Below is the session I used and later emailed to him. You can see a few spots at the bottom of the example where I was unsure of the syntax on passing an empty parameter array, but I figured it out.

This is a good example of why I like Powershell :-)

  1 [1] » "haha".gettype()
  2
  3 IsPublic IsSerial Name                                     BaseType
  4 -------- -------- ----                                     --------
  5 True     True     String                                   System.Object
  6
  7
  8 [2] » $temp = "haha".gettype()
  9 [3] » $temp.GetProperties()
10
11
12 MemberType    : Property
13 Name          : Chars
14 DeclaringType : System.String
15 ReflectedType : System.String
16 MetadataToken : 385875994
17 Module        : CommonLanguageRuntimeLibrary
18 PropertyType  : System.Char
19 Attributes    : None
20 CanRead       : True
21 CanWrite      : False
22 IsSpecialName : False
23
24 MemberType    : Property
25 Name          : Length
26 DeclaringType : System.String
27 ReflectedType : System.String
28 MetadataToken : 385875995
29 Module        : CommonLanguageRuntimeLibrary
30 PropertyType  : System.Int32
31 Attributes    : None
32 CanRead       : True
33 CanWrite      : False
34 IsSpecialName : False
35
36
37
38 [4] » $temp.GetProperties()[0]
39
40
41 MemberType    : Property
42 Name          : Chars
43 DeclaringType : System.String
44 ReflectedType : System.String
45 MetadataToken : 385875994
46 Module        : CommonLanguageRuntimeLibrary
47 PropertyType  : System.Char
48 Attributes    : None
49 CanRead       : True
50 CanWrite      : False
51 IsSpecialName : False
52
53
54
55 [5] » $temp.GetProperties()[0].name
56 Chars
57 [6] » $temp.GetProperties()[1].name
58 Length
59 [7] » $temp.GetProperties()[1].GetGetMethod()
60
61
62 Name                       : get_Length
63 DeclaringType              : System.String
64 ReflectedType              : System.String
65 MemberType                 : Method
66 MetadataToken              : 100663629
67 Module                     : CommonLanguageRuntimeLibrary
68 MethodHandle               : System.RuntimeMethodHandle
69 Attributes                 : PrivateScope, Public, HideBySig, SpecialName
70 CallingConvention          : Standard, HasThis
71 ReturnType                 : System.Int32
72 ReturnTypeCustomAttributes : Int32
73 ReturnParameter            : Int32
74 IsGenericMethod            : False
75 IsGenericMethodDefinition  : False
76 ContainsGenericParameters  : False
77 IsPublic                   : True
78 IsPrivate                  : False
79 IsFamily                   : False
80 IsAssembly                 : False
81 IsFamilyAndAssembly        : False
82 IsFamilyOrAssembly         : False
83 IsStatic                   : False
84 IsFinal                    : False
85 IsVirtual                  : False
86 IsHideBySig                : True
87 IsAbstract                 : False
88 IsSpecialName              : True
89 IsConstructor              : False
90
91
92
93 [8] » $temp.GetProperties()[1].GetGetMethod().Invoke
94
95
96 MemberType          : Method
97 OverloadDefinitions : {System.Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo cu
98                       lture), System.Object Invoke(Object obj, Object[] parameters)}
99 TypeNameOfValue     : System.Management.Automation.PSMethod
100 Value               : System.Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo cul
101                       ture), System.Object Invoke(Object obj, Object[] parameters)
102 Name                : Invoke
103 IsInstance          : True
104
105
106
107 [9] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", [])
108 Unable to find type []: make sure that the assembly containing this type is loaded.
109 At line:1 char:65
110 + $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", []) <<<<
111 [10] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world")
112 Cannot find an overload for "Invoke" and the argument count: "1".
113 At line:1 char:47
114 + $temp.GetProperties()[1].GetGetMethod().Invoke( <<<< "hello world")
115 [11] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", {})
116 Exception calling "Invoke" with "2" argument(s): "Parameter count mismatch."
117 At line:1 char:47
118 + $temp.GetProperties()[1].GetGetMethod().Invoke( <<<< "hello world", {})
119 [12] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", $Null)
120 11
121 [13] »
122

Note - I used the :toHTML command from Vim along with Peter Provost's Powershell syntax file to get the color. Powershell doesn't support color at the console like this yet without explicitly passing color arguments to Write-Host.

posted on Wednesday, May 07, 2008 7:51:00 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, April 24, 2008

(Warning - this post is both a rant against the Mutex as well as a guide for its usage. Also, don't blindly copy code, only the bottom code snippet works. :-) )

I'm a big fan of an API that is so easy to use that I don't have to look at the documentation.

I had to look up the documentation for System.Threading.Mutex... multiple times.

Taking a look at Mutex, I see that it implements IDisposable. Great, that means I can wrap it in a using block.

My first try:

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    MessageBox.Show("Press OK to release the mutex.");
}

Looks good, right? Nope, that is a big negative. Nowhere does this actually acquire the mutex. When you run this application twice, they both show the message box just fine. Maybe I should actually check the createdNew value?

Let's change the code to look like this:

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    if (!createdNew)
        mtx.WaitOne();
    MessageBox.Show("Press OK to release the mutex.");
}

However, that didn't work, either. It turns out that the createdNew parameter just tells you if you're the one who created the mutex, not if you currently own the mutex. That is what the purpose for the WaitOne method is for. Of course, the documentation just says that it "blocks the current thread until the current WaitHandle receives a signal." Okay. Well, I'm glad that I now know that it also waits for my thread to acquire a lock on the mutex. (note, if you pass in 'true' as the first parameter, you'll request to be the owner, but you'll only be the owner if the createdNew out parameter comes back with true)

Third try. Third time's the charm, right?

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    mtx.WaitOne();
    MessageBox.Show("Press OK to release the mutex.");
}

Great, now when I run my app twice, the second one is blocking on the WaitOne call. Cool. You can even tell in the below screenshot, because the button's paint event is blocked and is whiting out (like Solitaire does when you win!).

image

Let's click okay and see if the second form gets the mutex, thus displaying the message. That's weird - the form still isn't responding. Let's close the first form.

image

Ouch! That was unexpected. What? Abandoned mutex? This sounds like I never even released the mutex. Hmmm... ReleaseMutex? Shouldn't that be called from the Dispose (end of the Using block)? Might as well try it.

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    try
    {
        mtx.WaitOne();

        MessageBox.Show("Click OK to release the mutex.");
    }
    finally
    {
        mtx.ReleaseMutex();
    }
}

Finally! Now, it works like I'm wanting. I'm keeping the using block in place, because that disposes the WaitHandle that Mutex uses (Mutex in face inherits from WaitHandle).

Anyway, I'm hoping there is a reason for the API to be designed in this way, but man, it doesn't seem very intuitive to me.

While learning this, I unfortunately tried putting the Mutex in some of my code without trying it small scale first. After struggling for quite a while, I went to the small application and discovered everything that I've posted here. I hope this helps you with the Mutex when you have to deal with it.

posted on Thursday, April 24, 2008 2:48:19 PM (Central Standard Time, UTC-06:00)  #    Comments [0]

Here is a simple script I wrote which was inspired by this post on terminal color highlighting and by ColorDiff that does essentially the same thing.

# Out-ColorDiff.ps1
Process {
    if ($_) {
        foreach ($line in $_) {
            if ($line -match '^[<|-]') {
                Write-Host -ForegroundColor red $line
            }
            elseif ($line -match '^[>|+]') {
                Write-Host -ForegroundColor green $line
            }
            else {
                Write-Host $line
            }
        }
    }
}

Here is a screenshot of sample output from the script:

image

You can use it by piping the diff output to the script, like 'svn diff somefile | out-colordiff' or if you're stuck using something like MKS, you can use 'si diff somefile | out-colordiff'.

Possible (and easy) additions would be to add direct parsing of a file instead of taking an argument off of the pipeline. This is all I need currently, but if you wish to add more features, feel free to leave them in the comments.

posted on Thursday, April 24, 2008 9:55:44 AM (Central Standard Time, UTC-06:00)  #    Comments [0]

image

(Sorry for the lack of substance with this blog post - I'm hoping that just posting anything will spur me on to post something with substance. Wish me luck.)

posted on Thursday, April 24, 2008 8:06:17 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Friday, March 28, 2008

Just a reminder to anyone in the Fort Smith area - we'll be meeting next Monday night at 6:00 to hear Chris Koenig talk about Silverlight. Chris is a Microsoft Developer Evangelist located out of Dallas. I got to meet Chris last year for a grand total of about 5 minutes when I went down for the .NET Roadshow that was hosted at Microsoft's office in Dallas. Chris got to escort me and the others between floors on the elevator :-)

Anyway, if you're in the area, swing by. We'd love to see you. For more information, check out the FSDNUG website.

posted on Friday, March 28, 2008 3:24:36 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Wednesday, March 26, 2008

If you've been working with the .NET Framework for a while, you're hopefully already using some form of static analysis to help you catch problems with your code. One of the most well known is Microsoft's FxCop, which is now integrated as the Code Analysis feature in Visual Studio 2005 [1] and up. If you're not already using this tool, then please start because it can help you find problem areas like potential NullReferenceExceptions as well as globalization and security issues.

However, while FxCop is great at catching small problems and details, it isn't the best tool to see the big picture regarding your software. Enter NDepend by Patrick Smacchia. Chances are, you've already read Scott Hanselman's great review of NDepend a while back (or heard his podcast on static analysis with NDepend). If you haven't read it, go ahead and check it out. Scott uses NDepend to analyze dasBlog (which I'm running), so you can get the general feel for working with NDepend and what the reports look like.

I'd like to run through a few of the features of NDepend using Rhino Mocks as the target of my static analysis. Rhino Mocks is a neat example because it is only one assembly, but it is the result of an ILMerge of quite a few different libraries, so we get to see how NDepend handles this. Here is NDepend's class browser showing Rhino Mocks:

image

As you can see, it handles Rhino Mocks accurately. In fact, it almost feels like the class browser in Reflector, so that is already a plus. In fact, as you can see, the context menu supports jumping to Reflector for the selected type.

The "Who is directly using me?" option is also pretty cool and highlights the extensive use of CQL in NDepend:

image

CQL, or Code Query Language, is the centerpiece of NDepend and is how all of the analysis happens. You can think of it as SQL against IL. The massive benefit that NDepend has over FxCop IMHO is that you can create your own analysis rules in CQL instead of having to write and compile a DLL to extend FxCop (for an example of this, check out this FxCop rule that ensures that ArrayLists are List<T>s instead). Even better, NDepend provides a complete editor with intellisense that allows you to test your queries out against your assemblies.

image

Take a look at this screenshot. You can see the intellisense at the bottom right hand of the screen. At the top left is the CQL Query Results. The top right is all of the types in the assemblies, but the highlighted ones in blue are those that were returned by the query. This all happened as I typed the query in. Actually, I got red when I typed it in the first time, because my query had some mistakes in it, but NDepend was very helpful in showing me how to correct my query.

The query editor also has different types of intellisense depending on the value.

image

I'll admit that it might seem weird to have a slider when you're just typing a number in, but the cool part is when you change the value, the query results automatically change to reflect the new value. In this case, you can watch the results of the query to get a feel for which types have the most methods.

From an agile coding perspective, NDepend ties in well with Continuous Integration. It ships with both a NANT and an MSBuild task to run the NDepend console against an NDepend project file (which is just XML). The report that it provides is insanely detailed. I'd say this where the value of application-specific CQL queries would come in handy, because you can come up with some detailed queries that are run on every CI build to ensure that the code still matches whatever design criteria was decided upon when the queries were written.

 image

For future versions of the tool, I'd think it would be neat to have a lightweight version of the CQL tool that you could ad hoc queries against assemblies, like as a Reflector addin or something. That'd be cool. Or maybe a Powershell cmdlet/PSDrive provider so that you could do something like this:

Get-ChildItem -Include *.dll -Recurse | Select-Cql -Top 10 -Methods -Where MethodCa -ge 5

Or maybe:

Get-ChildItem -Include *.dll -Recurse | Select-Cql -Top 10 -Methods | Where { $_.MethodCa -ge 5 }

I'm not sure exactly how the syntax might look, but it would be really cool :-)

Hopefully, I've given you a good picture of the some of the features of NDepend. If your interest is at all piqued, there is a "Trial / Open Source / Academic Edition" that you can download for free. Its feature set isn't quite as broad as the Professional edition, but I've used it before and it still provides a lot of functionality. Check it out!

 

Full Disclosure - I used a review copy of NDepend for this post. My company is not (yet) using this tool, but I think that there is interest. I wasn't paid to do this. <kidding>If you, dear reader, would like to pay me, please contact me.</kidding>

 

[1] I don't believe that all of the SKUs of Visual Studio have the Code Analysis feature.

Technorati Tags: ,
posted on Wednesday, March 26, 2008 6:58:49 AM (Central Standard Time, UTC-06:00)  #    Comments [1]
 Thursday, March 20, 2008

image

Anyone else find this funny? I know I do! I told you I was a beta junkie.

Technorati Tags:
posted on Thursday, March 20, 2008 7:50:31 AM (Central Standard Time, UTC-06:00)  #    Comments [0]