Archive for category Uncategorized

Move to WCF 4.0 for Less Configuration/Code

People have lots of complaints around WCF. For the 3.x codebase, many don’t like the amount of configuration one has to write or code in order to get a service up and running. For example, let’s assume that we have a simple service contract, IEchoService.

[ServiceContract(Namespace="http://www.friseton.com/Echo")]
interface IEchoService
{
  [OperationContract]
  string Echo(string value);
}

The class is implemented by EchoService:

class EchoService : IEchoService
{
  public string Echo(string value)
  {
    return value;
  }
}

In .NET 3.x, we would then have to setup some endpoints, each endpoint specific to the protocol we wanted to understand. We had to remember things like “URLs that begin with net.tcp use the NetTcpBinding.” For intranet and local machine communication, this is a pain in the butt. In .NET 4.0, the common case of taking the defaults is much easier. If you plan on listening at the base URL(s) for the service, a console application can look like this:

(code only)

var netTcp = new Uri(string.Format("net.tcp://{0}/EchoService",
  Environment.MachineName));
var netPipe = new Uri(string.Format("net.pipe://{0}/EchoService",
  Environment.MachineName));
using (var host = new ServiceHost(typeof(EchoService), netTcp, netPipe))
{
  host.Open();
  Console.WriteLine("Press [Enter] to exit.");
  Console.ReadLine();
}

You could also configure the base URIs if you wanted this all to be dynamic. This mechanism only works if you don’t explicitly add any endpoints. Choosing to add any endpoint: discovery, metadata, or a specific contract WILL mean you have to specify everything. The implicit behavior will expose all contracts on the endpoint, so a service that implements 2 or more contracts will listen for all contracts when you use implicit listeners.

Leave a comment

More with Discovery, Day 4

Previously, we looked at configuring discovery on the server. What about the client? To discover from the client, we use a class named DiscoveryClient. DiscoveryClient implements the WS-Discovery protocol. Discovery is typically done over UDP because UDP allows for endpoints to broadcast a message.

The client uses a FindCriteria instance. In our case, we will ask for discovery to give us the metadata exchange endpoints that have definitions for ITest. Upon finding 1 of these, or timing out, we will resolve the metadata exchange endpoint and ask for information about the endpoint. If at least one of those is found (which it should be but it may disappear in between the first request and this one), extract the ITest information and create an ITest ChannelFactory using the discovered binding and endpoint. Sample code looks exactly like this:

// Create a client to find ITest instance. Return as soon as
// 1 is found.
var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var criteria = FindCriteria.
  CreateMetadataExchangeEndpointCriteria(typeof (ITest));
criteria.MaxResults = 1;
var findResponse = discoveryClient.Find(criteria);
discoveryClient.Close();
if (findResponse.Endpoints.Count > 0)
{
  // Resolve the metadata for the first address.
  // Return the binding and address information.
  var endpoints = MetadataResolver.Resolve(typeof (ITest),
    findResponse.Endpoints[0].Address);
  if (endpoints.Count > 0)
  {
    // Create a factory based on the binding and address information
    // we received from the metadata endpoint.
    var factory = new ChannelFactory<ITest>(endpoints[0].Binding,
      endpoints[0].Address);
    var channel = factory.CreateChannel();

    // Call the add function
    Console.WriteLine(channel.Add(3, 4));
    factory.Close();
  }
}

The above code will fail if authentication credentials other than Windows or anonymous are required. But, if you use standard windows authentication on the service (or nothing) this works well. Discovery is well suited to intranet scenarios, because things like Windows identities and authentication are already in use.

Leave a comment

More with Discovery, Day 3

By now, you might be wondering where a person would actually use discovery. A common case would be allowing two processes on the same machine to find each other and allow for dynamic naming of all endpoints (such as using GUIDs in the URLs). This could be used by every Windows Service that has an application running in the system tray. In the enterprise, you would use discovery as one part of a publish and subscribe system. The subscribers would query for all endpoints that publish some kind of information (which would allow the subscribers to poll). Alternatively, a publisher could periodically ask for all entities on the network that were interested in a given topic and push to those endpoints. Likewise, a client could look for a service that implemented some other functionality and dynamically configure itself (instead of needing a priori knowledge about how infrastructure is deployed).

To make a service discoverable on the server, you add a ServiceDiscoveryBehavior to the service. This behavior, when combined with a UdpDiscoveryEndpoint, allows the service to be found over a broadcast message sent on the network. If you want clients to be able to automatically configure themselves, you need to add an IMetadataExchange endpoint as well. The IMetadataExchange endpoint allows the service to send information about the contracts in use, the bindings against those contracts, and address information on where the service is listening for messages.

The following code constructs a ServiceHost for some service, TestService, that implements a contract named ITest.

var baseUri = string.Format("net.tcp://{0}/Test", Environment.MachineName);
using (var host = new ServiceHost(typeof(TestService), new Uri(baseUri)))
{
  // Make the service discoverable and make sure it has an
  // endpoint to announce its presence.
  var discoveryBehavior = new ServiceDiscoveryBehavior();
  discoveryBehavior.AnnouncementEndpoints.Add(
    new UdpAnnouncementEndpoint());
  host.Description.Behaviors.Add(discoveryBehavior);

  // Make sure the service can respond to probes.
  host.AddServiceEndpoint(new UdpDiscoveryEndpoint());

  // Add the ability to handle Metadata requests (aka WSDL)
  host.Description.Behaviors.Add(new ServiceMetadataBehavior());
  host.AddServiceEndpoint(typeof(IMetadataExchange),
    MetadataExchangeBindings.CreateMexTcpBinding(), "/mex");

  // Tell the service to listen for ITest messages on net.tcp
  host.AddServiceEndpoint(typeof (ITest), new NetTcpBinding(),
    string.Empty);

  // Open the host and start listening.
  host.Open();

  // Display what we are listening for
  foreach (var endpoint in host.Description.Endpoints)
  {
    Console.WriteLine("{0}: {1}",
      endpoint.Contract.Name,
      endpoint.ListenUri);
  }

  // Wait until we are done.
  Console.WriteLine("Press [Enter] to exit");
  Console.ReadLine();
}

 

With this code, we have a service that is discoverable and callable without requiring a client to have any code or configuration that is specific to our service (though it may if the developer chooses).

Leave a comment

Limiting time for Discovery Part II

Previously, I had thought I found a way to speed up discovery by limiting the search time. It turns out that there are better ways to achieve the same goal. When limiting duration, you are trying to find all endpoints implementing a given contract within a specific period of time. However, you may have other criteria, like you just want an endpoint that implements a contract. As soon as you find that endpoint, you are happy. This is pretty simple to do as well. On your FindCriteria object, just tell it you want it to stop when it finds 1 instance OR times out. Instead of setting the duration, set the MaxResults property to 1:

FindCriteria criteria = new FindCriteria(typeof(ITest));
criteria.MaxResults = 1;

That’s all there is to it!

Leave a comment

First Experiences with WS-Discovery

I was digging into WCF’s implementation of WS-Discovery today and was somewhat appalled by how long it took to discover a service from a client when both endpoints lived on the same machine. I setup tracing and message logging to dig into why things were taking so long. Inside the messages, I found this nugget in the WS-Discovery probe messages:

<s:Body>
  <Probe xmlns="http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01">
    <d:Types 
      xmlns:d="http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01" 
      xmlns:dp0="http://tempuri.org/">dp0:ITest</d:Types>
    <Duration 
       xmlns="http://schemas.microsoft.com/ws/2008/06/discovery">
       PT20S</Duration>
  </Probe>
</s:Body>

 

I thought to myself, “That looks like a TimeSpan. I wonder how I can set it.” If you haven’t used WS-Discovery on the client in WCF, let me walk you through the basic few lines of code that get things set up. You need a DiscoveryClient which knows how to send the probe messages and extract endpoints from the results. When the DiscoveryClient sends out a request, it sends out the request asking for services that implement a specific type. In our case, we are looking for a type in the http://tempuri.org/ XML Namespace where the type is named ITest.You state what you are looking for using a FindCriteria object. The code looks like this:

var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var criteria = new FindCriteria(typeof (ITest));
var findResponse = discoveryClient.Find(criteria);
 

Looking at the data which appeared in the Probe, I thought it looked at awful lot like FindCriteria since FindCriteria was the only thing I told about the type I wanted to talk to. I took a quick look at the FindCriteria object via IntelliSense and found a member called Duration. For grins, I set it to 100 milliseconds:

var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var criteria = new FindCriteria(typeof (ITest));
criteria.Duration = TimeSpan.FromMilliseconds(100);
var findResponse = discoveryClient.Find(criteria);

Suddenly, discovery ran faster. I also saw that the probe Duration was now set to PT0.1S.

So, what did I learn? I learned that, by default, Discovery on WCF will allow for 20 seconds to find all endpoints. If you know the endpoint is close and the collection of implementations is small, you can ratchet the discovery time down to something reasonable for your situation.

Leave a comment

How Office Automation Saved my Morning

I had procrastinated on mailing out information for the Chicago Give Camp. I wanted to make sure the email went out early in the week and in the morning so that people would probably read it. This morning, I was determined to get the mailing out. I started out brute forcing this thing, but the tedium hit me fast. Switching between apps, double checking that I copy/pasted the right info, and that I didn’t have any screw ups got to me fast-after about 6 messages. I had another 84 to go.

The email I was sending out was a classic form letter: insert recipients name in one spot, insert my info in a few others, and send. I wanted all the email history to show up in my Outlook ‘Sent Items’ and I wanted the message to look nice (aka HTML formatting). In about 20 minutes, I had the task completed and the email sent. Here is  what I did:

1. I saved the form letter as HTML and made sure that the fields to replace were easily identified. I was going to use string.Replace(string, string) to fill in the form fields. I added the HTML file to the solution and told VS to copy the file to the output directory on build. The file isn’t a resource, just an asset that shows up in a well known location.

2. I identified where I needed to stop and start in the spreadsheet. I was on row 8 and needed to go through row 89. I didn’t need a general purpose solution, I needed something that saved me from mind-numbing tedium, so I hard coded these values.

3. I identified which columns contained the information I needed and ran a quick test to get the values out of the cells from Excel.

4. I tested a couple of times with sending the email  to myself instead of to the actual recipient. This was a low bar unit test that was easy to remove once things appeared to work.

5. I changed the code to send to the actual recipient and, once all the messages went out, marveled at a job well done!

As software developers, we frequently write tools that are meant to be general purpose. Some days, it’s fun to just write a piece of throwaway code that doesn’t solve any grand problems, but does allow you to get a one time task done quickly. Today was one of those days.

Here is the code, in case you are curious. Cut and paste into your own applications at your own risk. This code is not production ready, and other disclaimers that basically mean run  this code in a debugger.

static void Main(string[] args)
{
    var excelApp = new Microsoft.Office.Interop.Excel.Application();
    var outlookApp = new Microsoft.Office.Interop.Outlook.Application();
    var spreadsheet = excelApp.Workbooks.Open(
          @"C:UsersScott SeelyDownloadsChicago Charities.xlsx");
    Microsoft.Office.Interop.Excel.Worksheet worksheet = spreadsheet.Worksheets[1];
    string originalEmail = File.ReadAllText("GiveCampLetter.htm")
          .Replace("[Insert your name]", "Scott Seely")
          .Replace("[insert your email]", "xxxx@xxxxx.xxx")
          .Replace("[insert your preferred contact number]", "847-xxx-xxxx");
    for  (int i = 8; i < 90; ++i)
    {
        dynamic realnameCell = worksheet.Cells[i, "C"];
        var realname = realnameCell.FormulaLocal;
        dynamic emailCell = worksheet.Cells[i, "F"];
        var email = emailCell.FormulaLocal;
        if (string.IsNullOrEmpty(realname) || string.IsNullOrEmpty(email))
        {
            continue;
        }
        Microsoft.Office.Interop.Outlook.MailItem mail = outlookApp.CreateItem(
          Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
        mail.Subject = "Midwest Give Camp";
        mail.To = email;
        mail.HTMLBody = originalEmail.Replace("[insert contact name]", realname);
        mail.Send();
        Console.WriteLine("{0}: {1}", realname, email);
    }
}

Leave a comment

Unit Tests in F#

In the F# community, I have seen a lot of talk about how cool functional programming is, how to use continuations, monads, and so on. I haven’t seen much about using F# for unit testing how to unit test F# code. I’ve been particularly interested in unit testing since I’ve started a larger web project and once I had my MVC controller ready, I wanted to run the unit tests. Since I’m pushing myself to use F# more, I’m writing the unit tests in F#.

I just want to let you know that writing a unit test in F# is as easy as anywhere else. After including a reference to MbUnit in my test assembly, I wrote a simple test like so:

namespace somenamespace.TestSuite
open MbUnit.Framework

[<TestFixture>]
type SampleTest() =
  [<FixtureSetUp>]
  member this.Setup() =
    // Do setup work
    ()

  [<FixtureTearDown>]
  member this.Teardown() =
    // Do tear down work
    ()

  [<Test>]
  member this.IAmATest() =
    Assert.AreEqual(1, 1, "This was supposed to work")
    ()

For you C#/C++ folks, the empty parens () at the end of the functions just state that the member has a void return type. For the VB.NET folks, it is the same as a Sub.

And yes, all the other attributes you expect from MbUnit do work just fine in F#. When you add F# to your toolbox, you can leverage the time you spent learning unit testing frameworks. Hopefully, this makes the transition a little more appealing.

Leave a comment

Windows Phone DevCamp: Chicago, April 10

This is a DevCamp. In the morning, we’ll get an overview of how to use the toolchain. After that, we eat and build a number of kick-ass applications on Windows Phone 7 emulators.

That’s it. Just devs in a room learning about Windows Phone 7.

Tentative Schedule:

8:30- Checkin

9:30-12:00 Presentation on Windows Phone 7 and how to develop on it

12:00 Lunch

1:00-5:00 Attendees build apps

5:00-6:00 Judge apps

6:00-6:30 Hand out awards

6:30 event is over, go home.

I look forward to meeting you. See you there!

Events

Leave a comment

Silverlight Printing

I have had a project on my “I should build that” list for several years. I do volunteer work with the Racine/Kenosha Wisconsin Friends of the NRA. Every year, we (and many other FNRA groups across the USA) host an event that raises money to support the shooting sports community in Wisconsin. This money funds range improvements, youth hunting programs, events for veterans, and other things the local shooting sports community needs. Part of the fund raising is a raffle we do every year. To run the raffle, we print the tickets early and sell them in the months leading up to our big banquet in October. The ticket printing gig fell to me since I grabbed the job.

For the past 2 years, I handled this job by printing the tickets from an Excel spreadsheet. I laid things out just so and was able to rifle through all the tickets, one page at a time, in about 90 minutes. I regularly messed up several sheets during  the printing because I would miss a number here or there. I looked at applications to print the tickets and thought “That looks easy. I should just build that.” 2010 printing season arrived and I finally did. Given that Silverlight now supports printing and I hadn’t tried anything interesting in printing reports with it, yet, I decided to build an Internet capable application to support my needs.

A few words first: this application supports my needs for tickets and mine alone. I needed to print a raffle ticket that had the following characteristics:

1. Prints to an 8.5″ x 11″ piece of paper.

2. Has 8 tickets per page.

3. Has the perforations where my sheets had perforations.

4. Prints a specific header for each stub.

5. Prints a user customized description to each ticket body.

6. Handles multipage printing.

This code is guaranteed to work on a Canon MP780 printer, because that is what I own. YMMV if you own a different printer. The app looks like this:

image

While printing these tickets, I found a the program refuses to handle documents larger than 34 pages or 272 tickets. This seems to be limited because Silverlight printing generates bitmaps which tend to be space intensive. At 34 pages, I’m seeing the print spool show 2GB+ of memory for the spooled job. My print server is a 32-bit Windows Home Server box-a 64-bit machine may do better.

The code

Adding a print handler to Silverlight is pretty easy. You need to make sure that printing is initiated from a user action with no other UI intervening in between the button click and the presentation of the print dialog. For example, you can’t add a MessageBox.Show(“Hi”) in between the button click and the creation of the print job. To handle the printing, you just need to create a System.Windows.Printing.PrintDocument, hook the PrintPage event, and go.

private void Button_Click(object sender, RoutedEventArgs e)
{
    var doc = new PrintDocument();
    var ticket = (Ticket) LayoutRoot.DataContext;
    var pageStart = ticket.FirstTicket;

    doc.PrintPage +=
        (s, eventArgs) =>
            {
                eventArgs.HasMorePages = (pageStart + 8) < ticket.LastTicket;
                eventArgs.PageVisual = GeneratePage(ticket, pageStart, eventArgs);
                pageStart += 8;
            };
    doc.Print("Tickets");
}

PrintPage passes a sender object and a PrintPageEventArgs instance to the event handler. PrintPageEventArgs has two propertiees that are important: HasMorePages and PageVisual. Set HasMorePages to true if the PrintPage event should be called again. If the code is printing the last page, set HasMorePages to false. The PageVisual property tells the runtime what should be printed. Any valid descendent of UIElement works here.

While doing this printing, I tried a few approaches before finding one that worked.Please note that I stopped writing code as soon as this thing worked. I first tried creating the entire page of tickets via code and no XAML assistance. Setting up the tickets went pretty well. I had a number of issues putting the exact correct transform on the ticket description so that it would rotate 90 degrees and appear in the right spot on each ticket. I was regularly off by a fraction of an inch on one ticket or another. After futzing with this for an hour, I tried setting up the entire page. This got to be hard because the data binding code and little adjustments were killing a lot of time. I believe I could have made either approach work eventually, but I wasn’t that interested in the puzzle to go that far.

My final solution was a combination of all in code and all in XAML: I designed a user control called ticket. You can see the ticket user control in the screen shot above. This had a few advantages:

1. I was able to add WYSIWYG display of the tickets to the user, so that surprises are minimized when printing tickets.

2. I could get the orientation of the bound data perfect in Expression Blend.

3. This was up and running in about 15 minutes from the time I started designing the ticket until it worked as a printout.

The layout code is handled by GeneratePage. I used StackPanels to hold the tickets and simplify the layout calculations. I used data binding to set the ticket numbers and ticket text. The one tricky part of the layout was taking account of the left and right margins. The tickets don’t change size, but the print area does for the tickets on the left and right side of  the page. You’ll see that for columns 0 and 3, the code handles the edges. You’ll also notice that the following code is single purpose-it only works for my ticket sheet.

private static UIElement GeneratePage(Ticket ticket, int pageStart,
    PrintPageEventArgs args)
{
    double gridHeight = args.PrintableArea.Height;
    double gridWidth = args.PrintableArea.Width + args.PageMargins.Left +
        args.PageMargins.Right;
    var retval = new StackPanel
                     {
                         Height = gridHeight,
                         Width = gridWidth,
                         Orientation = Orientation.Vertical
                     };
    for (var i = 0; i < 2; ++i)
    {
        // Add a StackPanel that has Horizontal layout
        var rowPanel = new StackPanel
                           {
                                Height = gridHeight/2,
                                Width = args.PrintableArea.Width,
                                Orientation = Orientation.Horizontal
                           };
        retval.Children.Add(rowPanel);
        // Add columns
        for (var j = 0; j < 4; ++j)
        {
            if (pageStart > ticket.LastTicket)
            {
                break;
            }
            var stackPanel = new StackPanel
                                 {
                                     Orientation = Orientation.Vertical,
                                     Height=rowPanel.Height,
                                 };
            rowPanel.Children.Add(stackPanel);
            switch (j)
            {
                case 0:
                    stackPanel.Width = gridWidth/4 - args.PageMargins.Left;
                    break;
                case 3:
                    stackPanel.Width = gridWidth/4 - args.PageMargins.Right;
                    break;
                default:
                    stackPanel.Width = gridWidth/4;
                    break;
            }
            var ticketControl =
                new TicketControl
                    {
                    LayoutRoot =
                        {
                            DataContext = new SimpleTicket
                            {
                                Text = ticket.TicketText,
                                TicketLabel = string.Format("No. {0:000}", 
                                     pageStart)
                            }
                         }
                    };
            stackPanel.Children.Add(ticketControl);
            ++pageStart;
        }
    }

    return retval;
}

Yes, I realize I could have bought their software for $30 and saved myself the time of writing this application. But, I wanted to learn how to use the print functionality in Silverlight, and $30 would not have taught me the stuff I learned by doing.

If you want to try out the application, I’ve put it up over here. Source code (Silverlight 4.0 RC) is here. Have fun!

Leave a comment

Review of RedGate .NET Reflector Pro

Disclaimer: RedGate is a sponsor of devlicio.us and offered a copy of the product and a ThinkGeek gift certificate as an incentive to review their product. This review is the work of the author and was not approved by anyone other than the author. There, now you know the kind of taint this review has. Please keep reading anyhow. OK? Good!

.NET Reflector is part of any respectable .NET developer’s tool belt. When you want to figure out how something works, why your code breaks when interacting with some library, you view the assembly through .NET Reflector’s lens. The latest version, 6.1.0.11, will display the IL in an assembly as IL, Managed C++, VB.NET, C#, Delphi, or Oxygene. The latest version has been updated to support .NET 4 and allows you to jump into .NET Reflector from Visual Studio. I was disappointed to see that the “Open in .NET Reflector” menu option is only available from the Object Explorer. I would have expected to see this option by right-clicking on the assembly from the References list in the Solution Explorer, but no. Given that other tools (TestDriven.NET in particular) do add this functionality (they actually add “Open in .NET Reflector” from the Solution Explorer!) RedGate needs to address this usability issue.

Otherwise, the free version of .NET Reflector hasn’t changed. It is still a great tool.

So, what about this new, Pro version? First, it costs $195 US. What do you get for that price? You get the ability to generate source code and PDBs so that you can step through the assemblies you use in the languages you know. If you are debugging Microsoft provided assemblies, you can already step through assemblies using the actual source (typically C#) through the Enable .NET Framework Source Stepping option from the Options dialog (in VS 2008/2010, access this dialog from Tools->Options menu.)

image

In the past, Microsoft wasn’t always good about keeping their symbol servers and source code servers up to date. Not every group put their code into the repository right away, so service packs and other patches might cause you to lose the ability to step through code. If you use components from other vendors, this option does you no good at all. RedGate is betting that a number of you want to be able to step through all .NET assemblies in VB.NET or C#. At a high level, RedGate generates the source code for an entire assembly and dumps it onto disk. It also writes out a PDB that tells Visual Studio how to map the assembly code to the generated code.

To long time users of .NET Reflector, the code generation piece may sound like old hat. It is. Back in May of 2004, Denis Bauer released a .NET Reflector plug-in that dumps the assembly information as code files (the plug-in was last updated for .NET Reflector v5). If you want a full project file for the dumped files, you used Jason Bock‘s FileGenerator plugin. Unfortunately, neither of these allow you to step through code, and that’s what many of us need. .NET Reflector Pro adds that functionality.

The overall experience is seamless. Upon running .NET Reflector, the .NET Reflector top level menu is added to Visual Studio 2008/2010. From here, you can either decompile an assembly in your project, Explore Decompiled Assemblies, or Debug an Executable.

Explore Decompiled Assemblies just pops open the Object Explorer in Visual Studio. I would have expected the list to be reduced to the list of assemblies I had already decompiled, but that isn’t what happened. Debug an Executable is a bit confusing too-it just fires up the executable and attached the debugger. If you have decompiled the assemblies of interest already, you can step through that code. Otherwise, this feature seems to be a bit of a waste. When PDB information does not exist, I would have expected the UI to say something like “.NET Reflector has not created debugging information for the selected executable. Would you like to generate source code and PDBs now?” I should then be able to select the assemblies I want to debug using this new functionality.

All that said, the tool does redeem itself. When selecting .NET Reflector->Choose Assemblies to Debug, the tool gets things right. This is the only feature in the Pro version that seems to have been completely thought out. At this stage, you are presented with the following dialog:

image

You can generate the source in C# v2.0/3.0 or Visual Basic 8.0/9.0. You then select the assemblies you would like to be able to step through and press OK. A little while later (time completely dependent on the size of the assembly), you are ready to do source level debugging. In the I tested out, this worked as advertised. I was able to step into System.dll, System.Web.dll, and other assemblies I regularly use. So, for .NET 4.0, clearly a win. F11 works fine, you can set breakpoints etc. For .NET 4.0 developers, this will be very helpful debugging those nasty issues where you need to figure out why your code is causing .NET and other libraries to die.

So, how about Silverlight? I had .NET Reflector generate the source/debug information for System.Windows. Then, I set a breakpoint in the constructor for my Silverlight MainPage.xaml.cs. I was able to step out to MS.Internal.CoreInvokeHandler.InvokeEventHandler.

image

I tried doing the same thing with the just released Windows Phone SDK. In this case, I was unable to get the application to rebuild correctly and work. After instructing .NET Reflector to generate the information for System.Windows for a Windows Phone Application, I saw this dialog:

image

After generating the assemblies, Reflector pointed the references in the solution to the new assemblies. Upon debugging, I saw this message (followed by several more for the other updated assemblies):

—————————

.NET Reflector
—————————
The loaded assembly "System.Windows" is not the one .NET Reflector expected.

Expected version: "c:tempregenSystem.Windows.dll"

Loaded version: "System.Windows.dll"

If the correct assembly is not loaded, debugging may not work.
—————————
OK  
—————————

If you are doing any Windows Phone development, the tool does not work for you. I imagine that this shortcoming will be addressed in the coming months-the SDK was only recently released.

Other things I noticed

The source code gets dropped into an AppData folder. For example, the code for MS.Internal.CoreInvokeHandler is at:

C:UsersScott SeelyAppDataLocalRed Gate.NET Reflector 6CacheV4x86CSV35c46bf0b4-91fb-4aa9-8732-63fe4e8d7afcMSInternalCoreInvokeHandler.cs

Looking in the v35 directory, we see that a PDB is dumped out:

imageThe assemblyLoc file corresponding to the System.Windows.PDB file has the following contents:

c:Program Files (x86)Reference AssembliesMicrosoftFrameworkSilverlightv4.0System.Windows.dll

For an assembly in the GAC, System.Windows.Forms, the assemblyLoc file points to it’s GAC location:

C:WindowsMicrosoft.NetassemblyGAC_MSILSystem.Windows.Formsv4.0_4.0.0.0__b77a5c561934e089System.Windows.Forms.dll

which appears to say that the symbols are generated from that particular reference assembly. The GUID named folder contains source code. 

Summary

Having access to source and single stepping helps me troubleshoot problems faster because I can see why the underlying code doesn’t like what I’m doing when consuming the class libraries. Like most developer tools, this one has its value in the time savings you will get by getting you to the why of a bug in less time. I like the tool because it doesn’t change how I do my day job. It gives me access to more code so I can poke down the debug path even further without pulling out Reflector to grok why my code isn’t behaving as expected. And, I can easily make stepping into other people’s code part of my daily workflow.

Overall, I like the enhancements and am looking forward to using .NET Reflector Pro.

Leave a comment