Archives for category: .NET

Last week, the first public beta of the Microsoft.Diagnostics.Runtime library was released. This is a very cool library that can be used to write automated dump analysis of processes hosting the CLR.

One of the first things you will need in order to use ClrMD is get a hold of the DAC library for the specific version of the CLR that your dump/live process is using. If this is a local dump/process, then you’ll have the DAC handy, as it will be part of your .NET Framework installation (example: c:\windows\Microsoft.NET\Framework64\v2.0.50727\mscordacwks.dll).

If you’re inspecting a dump from another machine, then you could also copy the mscordacwks.dll from the right folder in the remote machine. A more interesting option, however, is to dynamically fetch the right DAC library from the public Microsoft Symbol Server. ClrMD does not have built-in code to do this, and it can be a bit tricky, but it’s possible to implement it relatively easy in many scenarios.

In order to do this, you first need find two native libraries and copy them over to the same directory your application executable is located:

  • dbghelp.dll
  • symsrv.dll

The right place to pick these up is as part of the Debugging Tools For Windows package. Remember that you need to pick these for the right bitness (x64 or x86) depending on your process architecture, which needs to match the architecture of the dump/process you’re going to be inspecting. For this case, I picked the debugger tools package that comes with the Windows 8 SDK. When you install the tools from the SDK installer, these get installed to c:\Program Files (x86)\Windows Kits\8.0\Debuggers.

For this sample, you need to put the x64 and x86 versions of the libraries in the corresponding folder under .\dbglibs in the project folder. A custom build action will then copy the right version over to the output directory:

copy "$(ProjectDir)dbglibs\$(PlatformName)\*.dll" "$(TargetDir)"

The relevant code can be found in the DacLocator class. This class will load the dbghelp.dll library and initialize it. Using it is relatively simple:

dacloc = DacLocator.FromPublicSymbolServer(localCachePathTextBox.Text);
DataTarget dt = DataTarget.LoadCrashDump(dumpFileTextBox.Text);
String dac = dacloc.FindDac(dt.ClrVersions[0]);

Here we’re just initializing the library to use the public Symbol Server and using the specified path as the local cache, and then attempting to locate the DAC library that is required. Finding the DAC itself is done using the SymFindFileInPath() function:

StringBuilder symbolFile = new StringBuilder(2048);
if ( SymFindFileInPath(ourProcess.Handle, searchPath, dacname,
    timestamp, fileSize, 0, 0x02, symbolFile, IntPtr.Zero, IntPtr.Zero) ) {
  return symbolFile.ToString();
} else {
  throw new Win32Exception(String.Format("SymFindFileInPath() failed: {0}", Marshal.GetLastWin32Error()));
}

The rest of the sample is pretty straightforward: It just iterates through all objects in the heap, looking for HttpContext items and then
printing out some basic details of each one:

private IEnumerable<HttpCtxtInfo> FindHttpContexts(ClrRuntime clr) {
  ClrHeap heap = clr.GetHeap();
  foreach ( ulong addr in heap.EnumerateObjects() ) {
    ClrType type = heap.GetObjectType(addr);
    if ( type == null ) continue;
    if ( type.Name != "System.Web.HttpContext" ) continue;

    yield return GetHttpContextInfo(heap, addr, type);
  }
}

private HttpCtxtInfo GetHttpContextInfo(ClrHeap heap, ulong addr, ClrType type) {
  HttpCtxtInfo info = new HttpCtxtInfo {
    Address = addr
  };
  ulong reqAddr = (ulong)type.GetFieldByName("_request").GetFieldValue(addr);
  ClrType reqType = heap.GetObjectType(reqAddr);
  info.Method = (string)reqType.GetFieldByName("_httpMethod").GetFieldValue(reqAddr);
  info.Url = (string)reqType.GetFieldByName("_rawUrl").GetFieldValue(reqAddr);
  return info;
}

Running the sample app will look something like this:

DacSample Screenshot

The sample code can be downloaded here. Enjoy!

Just some fooling around with DynamicObject and friends in C# 4.0:


using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace ConsoleApplication1 {
   class DynamicTest : DynamicObject {
      public override bool TryInvokeMember(
            InvokeMemberBinder binder, object[] args,
            out object result) {
         var paramList = new Dictionary<string, object>();
         int i = 0;
         foreach ( object obj in args ) {
            string name = binder.CallInfo.ArgumentNames.Count > i ?
               binder.CallInfo.ArgumentNames[i] : ("param" + i);
            paramList.Add(name, obj);
            i++;
         }
         WriteCall(binder.Name, paramList);
         result = null;
         return true;
      }

      public void WriteCall(string name, Dictionary<string, object> paramList) {
         Console.WriteLine("Executing: {0}", name);
         foreach ( string key in paramList.Keys ) {
            Console.WriteLine("\t{0}: {1}", key, paramList[key]);
         }
      }
   }
   class Program {
      static void Main(string[] args) {
         dynamic cl = new DynamicTest();
         cl.MyMethodCall(count:12, value: "this is a string");
      }
   }
}

Executing it outputs this:

Executing: MyMethodCall
        count: 12
        value: this is a string

As Somasegar announced this morning, Visual Studio 2010 Beta 1 is now available for download for MSDN subscribers and will be available in a couple of days more broadly. I’m currently installing VS2010 and thought I’d mention a few things that occurred to me during the process.

Customizing the Installation

There seems to be a new screen for customizing the installation process:

vs10-setup

The idea is that you can select if you’re a .NET developer or a C++ developer and continue right away or then click the Customize button and see the old-style customization dialog that was in previous versions.

Maybe it’s just me, but I don’t see the point of this screen at all. Most people I know already customize the VS installation a lot, or will always install it complete, so it’s not like this is actually saving anyone time, is it?

Me? I’ll always go the customization road. For example, I never install Visual Basic; I have little use for it at this time. Oh, and by the way, don’t confuse Visual F# with Visual J# during the installation process :) .

While on the subject of customization, anyone know why SQL Server Compact is a required part of the Visual Studio installation? This has been that way for a few years now, and I still have no clue why I’d even want it install; I have yet to use it. Does VS use it itself for anything?

The Installation Process

The actual installation went by without any errors, and was relatively quick (certainly faster than I expected it). You’ll have to restart during the installation just after the .NET Framework 4.0 Beta 1 setup is done.

Unfortunately, I had to go through it twice because I incorrectly installed VC++ instead of VC#!

Something to watch out for: If you decide later to add/remove components, and you didn’t install the Sync Framework initially, it will come up checked by default as soon as you get to the component list screen. So if you didn’t want it, make sure to uncheck it before continuing with the setup.

The Windows SDK

Visual Studio 2010 comes with the Windows SDK 7.0A release (probably a beta build). One interesting thing about the SDK is that the /bin folder of the SDK contains the .NET 3.5 tools, while the new .NET Framework 4.0 SDK tools are contained inside the /bin/NETFX 4.0 Tools subdirectory. So make sure you’re using the right set of tools.

Visual Studio 2010

Launching the IDE for the first time is actually pretty fast; feels very snappy for a lot of things, which is pretty impressive for a beta 1 release.

It does a somewhat reasonable attempt at migrating your Visual Studio 2008 settings, though I noticed that some settings, like the color for line numbers and some of the tool window layouts are not migrated correctly.

The new Text Editor has a nice feel to it, and I rather like the new IDE look. A few comments on it:

vs10_editor

  • Borders/Margins between UI elements are a little on the big side, so there’s actually quite a few pixels of lost space there. If you look at the screenshot on the side, notice particularly that the border between the text editor window and the tool window tabs is actually fairly large.
  • The new WPF-based text editor renders the bold-as-italics in Envy Code R VS pretty badly. And still, several years later and a completely new text editor, and we still don’t have proper italics support. Seriously, people, how many more years do you want us to wait for it?
  • The text editor background color does not appear to be handled correctly. The Fonts & Colors dialog will say that the right background color is selected, but it does not get picked up when you start the IDE, defaulting to White every time.
  • One little nice thing I noticed is that the sample text on the Fonts & Colors dialog is now this:
    vs10_sample_text 
  • There’s a new feature in the editor: If you put the mouse pointer right on the vertical line with the +/- signs for the collapsible text, it will highlight the region of code that would get collapsed by the [-] sign right on top of the pointer:
    vs10_sel
    Unfortunately, there doesn’t appear to be a way to change the background color used for the selection. Or at least I couldn’t find it. I believe this is a side effect of not allowing the user to change the background color for Collapsible Text.
  • Font rendering on the IDE is, of course, very WPFy. Meaning, it’s not great. I think I can live with it on the editor itself (using a dark background seems to help a bit), but the IDE menus look, well, pretty bad:
    vs10_menus
  • The New Project Dialog has some changes. Some are good (and it looks nice, too), but some not as much. The description pane on the right is new, and well, it seems pretty useless to me for 90% of the project templates most people will use. It doesn’t help that the descriptions on the existing templates are pretty simple one-liners:
    vs10_new_proj 
    And by the way, the pane is not resizable at this time.
  • The new Text Editor does not appear to support splitting a code window horizontally, like previous versions did. I sure hope this gets fixed, because it’s a feature I use all the time :(

Conclusion

There is a lot of new stuff on the new IDE to look up, and tons more on the .NET framework. I hope to blog a bit about these in the next few weeks as I dig deeper into all the new stuff.

Last night I finally downloaded the RTM build of the recently released BizTalk Server 2009 and proceeded to install it on one of my dev virtual machines. Installation went without a hitch, very consistent with my experience with BizTalk installations since the 2006 release. (For what is worth, I never ran into any issues with the BTS2009 CTP installation before that either).

Unfortunately, not everything went as well. This particular VM was running BizTalk 2006 R2, so before installing 2009 I uninstalled the previous installation. While at it, I also uninstalled Visual Studio 2005, given how I was only using it for BizTalk dev and wouldn’t need it anymore on 2009.

As they said, this turned out to be a not so bright idea: I just noticed this morning that the VS2005 uninstall trashed my Visual Studio 2008 installation. Trying to open C# projects wouldn’t work anymore, complaining about the Windows Forms Visual Studio package being missing and not being able to create the compiler services and what not.

This kind of thing can completely screw up your morning and make you waste hours trying to get it fixed. Seriously, guys: supporting side by side installations also means supporting the corresponding uninstall process. One without the other is pretty damn useless.

I’m reinstalling VS2008 SP1 now and hoping that will fix it. If not, guess I might as well nuke this VM from orbit and start from scratch. This is not a good way to start my day…

Update: Nope, reinstalling SP1 did not fix it :(

I’ve been reading a bit about the Axum project from Microsoft, and I’m finding it pretty interesting. I’m just skimming the surface and to be honest I can’t say I understand much yet, but hopefully I’ll be able to play with it some more and get a better idea of its capabilities.

I think language/runtimes like this hold great potential for the applications that require a lot of concurrency, which should be more and more common in the future, so very much looking forward to what this develops into.

Unfortunately, right after installing the technology preview, I realized that the current Visual Studio package seems to be basically unusable for those of us liking dark themes, as it looks like this:

axum_vs

I couldn’t see any new options in the Font & Colors settings in Visual Studio that I could tweak to improve this, but I do hope they get added; this is just too painful :) .

Here’s a bug I had to diagnose this weekend that had me scratching my head for a bit before getting it. Consider this sample piece of code [1]:

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.Text;
using System.Threading;

namespace Winterdom.Samples {

   class Program {
      private const int LOGON32_PROVIDER_DEFAULT = 0;
      private const int LOGON32_LOGON_NETWORK = 3;

      [DllImport("advapi32.dll", SetLastError = true)]
      public static extern bool LogonUser(
          string lpszUsername, string lpszDomain, string lpszPassword,
          int dwLogonType, int dwLogonProvider, out IntPtr phToken
          );

      static void Main(string[] args) {
         AppDomain domain = AppDomain.CurrentDomain;
         domain.UnhandledException += (sender, e) =>
            Console.WriteLine(e.ExceptionObject.ToString());

         WindowsIdentity wi = new WindowsIdentity(GetLogon());
         WindowsImpersonationContext wic = wi.Impersonate();

         Timer timer = new Timer(
               (state) => {}, // do nothing on the callback!
               null, 3000, 3000
            );

         wic.Undo();
         // If we remove this line, no crash happens!
         wi.Dispose();

         Console.WriteLine("Wait for the crash!");
         Console.ReadLine();
      }

      static IntPtr GetLogon() {
         String user = "<USER HERE>";
         String pwd = "<PASSWORD HERE>";

         IntPtr token = IntPtr.Zero;
         bool success = LogonUser(
            user, ".", pwd, LOGON32_LOGON_NETWORK,
            LOGON32_PROVIDER_DEFAULT, out token
            );
         if ( !success )
            throw new System.ComponentModel.Win32Exception();
         return token;
      }

   }
}

Now put a valid username/password in GetLogon() and run it. Then watch the application crash with an unhandled exception in a secondary thread. You should’ve spotted an exception like this one:

System.ObjectDisposedException: Safe handle has been closed
   at System.Security.Principal.Win32.ImpersonateLoggedOnUser(SafeTokenHandle hToken)
   at System.Security.Principal.WindowsIdentity.SafeImpersonate(SafeTokenHandle userToken, WindowsIdentity wi, StackCrawlMark& stackMark)
   at System.Security.Principal.WindowsIdentity.Impersonate(StackCrawlMark& stackMark)
   at System.Security.SecurityContext.SetSecurityContext(SecurityContext sc, SecurityContext prevSecurityContext, StackCrawlMark& stackMark)
   at System.Threading.ExecutionContext.SetExecutionContext(ExecutionContext executionContext)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading._TimerCallback.PerformTimerCallback(Object state)

Why does it happen?

The problem appears because we impersonate an identity and soon after destroys the WindowsIdentity instance used to create impersonation token.

Between those two moments, we start a timer. When that happens, the runtime will capture the state of the calling thread, including its SecurityContext, and save it so that it can restore it on the background thread used to invoke the timer callback.

Since we destroy the WindowsIdentity instance soon after starting the timer, by the time the callback tries to fire, the authentication token has been closed already. The problem is that the framework makes no attempt to verify that the security context it saved is still valid before trying to impersonate the identity on the callback thread as well.

This leads to an unhandled exception which, on .NET 2.0, will cause your process to crash inevitably. It’s fair to say, though, that even if the framework actively checked for this condition and found that the authentication token was no longer valid, there would not be much else it could do, since it might be a bit dangerous to simply ignore it and invoke the thread on the original process security context (or at least it would lead to some unexpected behavior).

The bad part

The bad part about this issue is that you really don’t know who might be starting a new timer (or an y other framework facility that saves the SecurityContext for later use) in between your Impersonate() and Undo() calls.

For example, the original code I was tracking this problem in was a lot more complex, involving a custom Windows PowerShell host and the invoke-sqlcmd cmdlet that comes with SQL Server 2008. In that scenario, the problem wasn’t invoke-sqlcmd per se.

It just turned out that the ADO.NET Connection Pooling facilities will create background timers to handle cleanup of the connection pools the first time you get a new connection from the pool.

The really nasty part, however, was that the timer is created with a random interval, which meant you could never be sure when the process would crash: Sometimes it would happen just a few seconds after disposing the WindowsIdentity instance, sometimes several minutes later. This made figuring out the problem a lot harder.

[1] Yes, I’m aware the sample is leaking a handle, but that’s not really the problem.

As many have already heard or read, today Microsoft unveiled the Windows Azure Cloud Computing Platform. Besides allowing you to host your own applications, Azure also provides a Blob storage service, a Queue Service and a Table service exposed over REST-based HTTP endpoints.

Azuli is my attempt to write a client library for these services in Ruby. Since it’s one of my first attempts at any meaningful ruby code, it’s pretty ugly, but already usable to get started with it.

Currently there’s no documentation (except a few tests), but it already has the authentication bits in place for using the default Shared-Key authentication, and some basic facilities for interacting with the Blob service: You can create/list/delete containers, /create/retrieve/delete blobs.

I’ll be adding support for the Queue service soon and eventually for the Table service. Any feedback (particularly of the constructive kind) would be appreciated.

Code is at GitHub, so feel free to play with it, hack at it or whatever you want.

One of my development Virtual Machines has Visual Studio 2008 installed with SP1. For several reasons, I had not done a complete installation originally, but only certain pieces of it, like Visual C# and Visual Web Developer and some of the Team Developer tools.

A couple days ago turned out that it would’ve been really nice to also have Visual C++ install as well. I figured I could probably install the missing pieces and then apply SP1 again.

When I tried to do this, however, ran into a snag: I fired up the Visual Studio 2008 setup again, went into Add/Remove components and then, when the setup was initializing, I got an error to the effect that some components could not be loaded, and installation would cancel.

After trying a few times I gave up, started an older copy of the VM I had without SP1 installed and so was able to work around it after all, but still, I’m a bit curious. Has anyone else seen this? Is setup just foobar’ed after the installation of SP1?

After a few years, people still ask about my old FileMap library, a .NET wrapper for the Memory Mapped Files Win32 API, and I get occasional bug reports about it. It’s hard to believe I wrote the original code over 5 years ago!

Anyway, I’ve now cleaned up the code (alongside some of those fixes), and posted it to a GitHub repository as well. I’ve now updated the code to Visual Studio 2008 and cleaned up the unit tests.

I've been spending a bunch of time today doing some customization of some ASP.NET custom controls (yes, I know!). One of the things I needed to get working was decent design time support for a property of the control that returned an array of a simple custom structure.

[Browsable(true)]
public MyStruct[] StructData {
   get { return _structData; }
   set { _structData = value; }
}

This should've been simple, but it took me a far longer time than I expected to get working correctly. Getting the basic design time work done wasn't too much of a problem; since the property type was an array and not a custom collection, the default editors did the right thing and offered a good design time experience out of the box.

However, you still need to provide the designers and ASP.NET a way to store the property contents as an string, so that you can use markup to specify the value of the property.

Time to write a TypeConverter! I went ahead and wrote a simple TypeConverter that would take a string and return an array of structs based on its contents, or take an array and return a string based on the values in it. Nothing fancy.

I then enabled the type converter by using the TypeConverterAttribute on the property declaration:

[Browsable(true),
TypeConverter(typeof(MyStructArrayConverter))]
public MyStruct[] StructData {
   get { return _structData; }
   set { _structData = value; }
}

Once I added this, the designer worked right away. I could change the array contents in the designer, and it would get serialized into the aspx page markup correctly. Loading the page worked as well and all values would be correctly deserialized.

I thought I was home free until I tried to actually build the ASP.NET site (this was on a VS WebSite, not a Web Application Project). As soon as the ASP.NET compiler tried to compile the ASPX page hosting the control, it would error out with the dreaded error message:

Page.aspx (web): Object reference not set to an instance of an object.

That's it. No stack trace, no more details at all. I knew it was related to the TypeConverter, but that one was working correctly (already tested and verified). Checking further, I came to the conclusion that the error would appear every time that my TypeConverter.ConvertFrom() implementation would return an array with a non-zero size (useful, huh?).

So the array conversion was working perfectly, but ASP.NET was choking on the values contained in the array. At this point I realized the problem wasn't with the TypeConverter itself, but with how the ASP.NET was manipulating the values returned to generate the code from the ASPX page.

After much head-scratching and finding little explicit documentation about the issue I ran into this documentation piece on MSDN. The last section in the article talks about how "To implement a type converter that produces constructor-based property initialization code".

Based on that, I wrote my yet another custom TypeConverter that, following the guidelines on the article, implemented ConvertTo to convert from a MyStruct value to a corresponding InstanceDescriptor object. I applied this second TypeConverter to the struct declaration itself:"

[Serializable,
TypeConverter(typeof(MyStructConverter))]
public struct MyStruct {
   //...
}

And lo and behold, this time it worked perfectly: No complication errors anymore! Hopefully, next time I run against this and have forgotten again all about TypeConverters and its brethren, I'll remember to look here for hints :-).

Technorati tags: ,