Debugging a process that cannot be invoked through Visual Studio.

Sometimes it is rather difficult to debug through Visual Studio directly even although the project is right there in front of you. In my case I have an assembly that is invoked from a wrapper that is itself invoked from an MSBuild script. I could potentially get VS to invoke the whole pipeline but it seemed to me a less convoluted process to try and attach the debugger to the running process and debug from there.

But what if the process is something quite ephemeral. If the process starts up, does its thing, then shuts down you might not have time to attach a debugger to it before the process has completed. Or the thing you are debugging is in the start up code and there is no way to attach a debugger in time for that.

However there is something that can be done (if you have access to the source code and can rebuild).

for (int i = 30; i >= 0; i--)
{
    Console.WriteLine("Waiting for debugger to attach... {0}", i);
    if (Debugger.IsAttached)
        break;
    Thread.Sleep(1000);
}

if (Debugger.IsAttached)
{
    Console.WriteLine("A debugger has attached to the process.");
    Debugger.Break();
}
else
{
    Console.WriteLine("A debugger was not detected... Continuing with process anyway.");
}

You could get away with less code, but I like this because is is reasonably flexible and I get to see what’s happening.

First up, I set a loop to count down thirty seconds to give me time to attach the debugger. On each loop it checks to see if the debugger is attached already and exits early if it has (This is important as otherwise you could attach the debugger then get frustrated waiting for the process to continue.)

After the loop (regardless of whether it simply timed-out or a debugger was detected) it does a final check and breaks the execution if a debugger is detected.

Each step of the way it outputs to the console what it is doing so you can see when to attach the debugger and you can see when the debugger got attached, or not.

My recommendation, if you want to use this code, is to put it in a utility class somewhere that you can call when needed, then take the call out afterwards.

Changing the default Assembly/Namespace on an MVC appliction

TL;DR

When getting an error message like this:

Compiler Error Message: CS0246: The type or namespace name 'UI' could not be found (are you missing a using directive or an assembly reference?)

when compiling Razor views after changing the namespace names in your project, check the web.config file in each of the view folders for a line that looks like this:

<add namespace="UI" />

And update it to the correct namespace, e.g.

<add namespace="‹CompanyName›.‹ProjectName›.UI" />

Full story

I guess this is something I’ve not done before, so it caught me out a little.

I’ve recently created a new project and to reduce the file paths I omitted information that is already implied by the parent directory.

So, what I ended up with is a folder called ‹Company Name›/‹ProjectName› and in it a solution with a number of projects named UI or Core and so on. I then added a couple of areas and ran up the application to see that the initial build would work. All okay… Great!

I now have a source code repository that looks like this:

/src
  /‹CompanyName›
    /‹ProjectName›
      /UI
      /Core

In previous projects I’d have the source set out like this:

/src
  /‹CompanyName›.‹ProjectName›.UI
  /‹CompanyName›.‹ProjectName›.Core

While this is nice and flat, it does mean that when you add in thing like C# project files you get lots of duplication in the paths that are created. e.g. /src/‹CompanyName›.‹ProjectName›.Core/‹CompanyName›.‹ProjectName›.Core.csproj

Next up I realised that the namespaces were out as they were defaulting to the name of the C# project file name. So I went into the project settings and changed the default namespace and assembly name so that they’d be fully qualified (just in case we ever take a third party tool with similar names, so we need to ensure they don’t clash in the actual code). I also went around the few code files that had been created so far and ensured their namespaces were consistent. (ReSharper is good at doing this, so you just have to press Alt-Enter on the namespace and it will correct it for you)

I ran the application again and it immediately failed when trying to compile a Razor view with the following error message:

Compiler Error Message: CS0246: The type or namespace name 'UI' could not be found (are you missing a using directive or an assembly reference?)

Looking at the compiler output I could see where it was happening:

Line 25:     using System.Web.Mvc.Html;
Line 26:     using System.Web.Routing;
Line 27:     using UI;
Line 28:     
Line 29: 

However, it took me a little investigation to figure out where that was coming from.

Each Views folder in the application has something like this in it:

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="UI" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

There was my old “UI” namespace that had been replaced. It was these settings that were generating the using statements in the Razor precompiled source.

The solution was simple, replace that “UI” namespace with the fully qualified version.

        <add namespace="‹CompanyName›.‹ProjectName›.UI" />

And now the application works!

A better tracing routine

In .NET 4.5 three new attributes were introduced. They can be used to pass into a method the details of the caller and this can be used to create better trace or logging messages. In the example below, it outputs tracing messages in a format that you can use in Visual Studio to automatically jump to the appropriate line of source code if you need it to.

The three new attributes are:

If you decorate the parameters of a method with the above attributes (respecting the types, in brackets afterwards) then the values will be injected in at compile time.

For example:

public class Tracer
{
    public static void WriteLine(string message,
                            [CallerMemberName] string memberName = "",
                            [CallerFilePath] string sourceFilePath = "",
                            [CallerLineNumber] int sourceLineNumber = 0)
    {
        string fullMessage = string.Format("{1}({2},0): {0}{4}>> {3}", 
            memberName,sourceFilePath,sourceLineNumber, 
            message, Environment.NewLine);

        Console.WriteLine("{0}", fullMessage);
        Trace.WriteLine(fullMessage);
    }
}

The above method can then be used to in preference to the built in Trace.WriteLine and it will output the details of where the message came from. The format that the full message is output in is also in a format where you can double click the line in the Visual Studio output window and it will take you to that line in the source.

Here is an example of the output:

c:\dev\spike\Caller\Program.cs(13,0): Main
>> I'm Starting up.
c:\dev\spike\Caller\SomeOtherClass.cs(7,0): DoStuff
>> I'm doing stuff.

The lines with the file path and line numbers on them can be double-clicked in the Visual Studio output window and you will be taken directly to the line of code it references.

What happens when you call Tracer.WriteLine is that the compiler injects literal values in place of the parameters.

So, if you write something like this:

Tracer.WriteLine("I'm doing stuff.");

Then the compiler will output this:

Tracer.WriteLine("I'm doing stuff.", "DoStuff", "c:\\dev\\spike\\Caller\\SomeOtherClass.cs", 7);

Parser Error Message: Ambiguous match found

Symptom

On deploying a newly precompiled web site, the error message as displayed by ASP.NET is as follows:

Server Error in ‘/’ Application.


Parser Error

Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.

Parser Error Message: Ambiguous match found.

Source Error:

Line 1:  <%@ control language="C#" autoeventwireup="true" enableviewstate="false" inherits="WebSiteControls_Offers_TypeFilter, App_Web_typefilter.ascx.bd9a439f" %>

Line 2:
Line 3: <%--

Source File: /WebSiteControls/Offers/TypeFilter.ascx    Line: 1


Version Information: Microsoft .NET Framework Version:2.0.50727.3053; ASP.NET Version:2.0.50727.3053

System Information

This may or may not be relevant, but it reflects my set up at the time I discovered this issue.

  • Web Site project
  • Visual Studio 2008
  • .NET 3.5
  • IIS 6.0

 

Reason

The reason for this is that a control, in this case a Repeater, in the User Control had a similar name as a field on the code behind. The only difference between the two the case. One was called “offerTypes” (in the code behind, an IEnumerable containing entities from the business layer), the other “OfferTypes” (a ASP.NET Repeater control).

Solution

Rename one or other so that the names differ by more that case alone. In my case, I renamed the field referring to the entities to offerTypeInformation.

Tip of the Day #17: Duplicate input fields

Don’t allow duplicate input fields into your form.

The other day I was trying to debug a bug in an application that I maintain. The code created a set of pagination buttons at the top of the page with previous and next buttons. At some point a request had come in that the buttons needed to be replicated at the bottom of the page. Since the HTML was being built up in a string and dumped in a literal control in the first place the developer that was tasked with making the change just dumped the string into two literal controls, the original at the top of the page, and the new one at the bottom of the page. The previous and next buttons use hidden input field to tell the application which actual page number the buttons correspond to. And these were now duplicated and as a result the previous and next buttons ceased to work.

Here is an example of something similar:

<input id="first-hidden-field" value="123" type="hidden" name="some-name" />
<input id="submit-button" value="Submit" type="submit" />
<input id="second-hidden-field" value="456" type="hidden" name="some-name" />

When the form fields are returned to the application and the field “some-name” is queried the result back is a combination of the two fields with the duplicate name. In this case:

string someName = Request.Form["some-name"];

will result in the value of “123,456” being stored in the string. Basically, it is the comma separated form of all the input fields with the given name.

Errors like these drive me insane

Today I was trying to fix up a website for one of our clients. I got the site out of source control but somehow or other it wouldn’t compile. I’m not going to talk about the fact it didn’t compile out of the box – We all know that is not a good situation and the person who allows source to get into a state like that needs to be slapped repeatedly with a wet fish.

What I’m going to talk about is what the eventual error turned out to be because it is not something I’ve ever seen before and it was such a bizarre thing that I can only hope it isn’t common. But if you are afflicted by it you will be pleased to know that the solution is easy, even if the discovery of what the problem actually was wasted several hours.

If you are reading this then I suspect you will probably be suffering from this problem in which case you are probably now yelling “STOP BABBLING MAN AND TELL ME WHAT TO DO”.

First, a description of the problem:

There is an ASP.NET web site project (probably does the same thing on a web application… And let’s not get in to why this is a web site project, it’s an old project and the standard now is web applications) with a number of web forms in it.

The ASPX for the default page currently looks something like this:

<%@ Page Language="C#" AutoEventWireup="true"
      CodeFile="Default.aspx.cs" Inherits="Default" %>
<html>
<head><title></title></head>
<body>
    <form id="form1" runat="server">
        Stuff that's on my page
        <asp:Label ID="MyLabel" runat="server"></asp:Label>
    </form>
</body>
</html>

Nothing too odd about that, you might say… And you’d be right. There is nothing at all wrong with this page. However, when you go to compile your website you get this error:

Infuriation 2
The name ‘MyLabel’ does not exist in the current context

But… but… but… You can see that MyLabel exists on the ASPX page and if you type in the C# or VB source file you’ll see that intellisense finds the object perfectly well. So what is going on?

Well, it is interesting to note that Page1 and Page2 are very similar to Default. In fact, so similar that when they were created the person that did this just copied Default.aspx and Default.aspx.cs (or Default.aspx.vb if that’s your poison). What they didn’t do when they made the copies was to change the page directive at the top that has the Inherits attribute that points to Default. So, Page1 and Page2 are inheriting the behaviour in Default.

When this first happened that wasn’t a problem. Page1 and Page2 had just minor cosmetic differences, the behaviour was the same and no one noticed.

At some point later someone came along and added MyLabel to Default.aspx… This still didn’t make a difference. Everything worked as normal.

Then someone came along and realised that MyLabel needed to change on some condition and added some code into the Default.aspx.cs file that modified MyLabel. At this point all hell broke loose!

Suddenly, MyLabel can’t be found and no one can figure out why. It is there on the ASPX page, intellisense picks it up, the stupid compiler can’t see it.

The Solution

Eventually, after spending a couple of hours on the problem and batting it around some collegues and doing bit of brainstorming someone (let’s call him Craig Muirhead because he figured it out in the end and deserves the credit) comes up with the idea that perhaps other pages are inheriting the wrong class. A quick find in files on the name of the class and we found it was referenced by 4 other pages. It takes a matter of moments to fix all those files to point to their respective code behind files/classes rather than the one on our hapless page. And all of a sudden everything compiles.

Technorati Tags: ,,,,

Tip of the Day #7 (SysInternals)

I’ve visited the SysInternals site a few times over the course of my career because of some strange problem that I just couldn’t track down. The amount of information about what is actually happening on your system that the SysInternals tools provide is phenomenal. The site was run by Mark Russinovich and Bryce Cogswell until they got hired by Microsoft. However, the tools are still available and being updated, only now they are hosted by Microsoft themselves.

So, today’s tip is to visit the SysInternals page on Microsoft‘s TechNet site and familiarise yourself with what is available. You might find that one day it will save you hours of frustration.

The Conditional attribute in .NET

One of the odd thoughts that shoot across my brain today was how does Debug.Assert() work? I mean there are not separate debug and release builds of the .NET Framework so how does it know what sort of build it is?

A quick look in reflector revealed that Debug.Assert is defined as:

[Conditional("DEBUG")]
public static void Assert(bool condition, string message)
{
    TraceInternal.Assert(condition, message);
}

Interesting… I don’t recall having ever come across the Conditional attribute before.

What this actually does is tell the compiler to only call the method when the supplied preprocessor symbol is defined. The method will still be compiled and will still exist in the assembly. So, in a debug build a program that looks like this:

static void Main(string[] args)
{
    Debug.Assert(true, "This condition must be true");
}

will still look like that, but when compiled in release mode, will look like this:

private static void Main(string[] args)
{
}

But what about more complex code. What happens if the method call includes calls to other methods. Like this:

static void Main(string[] args)
{
    Debug.Assert(GetTheCondition(), GetTheMessage());
}

So be careful – If the calls made as parameters into a method such as Assert modify the state of the object then that won’t happen in release mode. For example, if the whole program looks like this:

class Program
{
    static int someState = 0;
    static string someOtherState = "123";

    static void Main(string[] args)
    {
        Debug.Assert(GetTheCondition(), GetTheMessage());
        Console.WriteLine("SomeState = {0}", someState);
        Console.WriteLine("SomeOtherState = {0}", someOtherState);
        Console.ReadLine();
    }

    private static string GetTheMessage()
    {
        someOtherState += "abc";
        return someOtherState;
    }

    private static bool GetTheCondition()
    {
        someState++;
        return (someState!=0);
    }
}

Then the output from a release build will be different from a debug build.

This is the debug output:

SomeState = 1
SomeOtherState = 123abc

And this is the release output:

SomeState = 0
SomeOtherState = 123

Tags: