harriyott.com

30 August 2006

Developer Xpress XtraGrid: adding a row in a hidden grid

Just had one of those mammoth "two of us trying to debug something weird for ages" sessions, which was ultimately successful, and hence rather satisfying.

The problem was in a DevX XtraGrid which was on the third tab of a tabbed form. Calling AddNewRow(), setting the data and then UpdateCurrentRow() on the grid only worked if the third tab had been clicked on. If the grid hadn't been made visible, then the row wasn't added.

Having tried a few things, I came across this
seemingly unrelated forum entry, and a hunch prompted me to download the example file. After chatting to the hunch for a bit, he went away, and I looked at the source in the example. Right in the middle of the example was a call to ForceInitialize(). I had no (okay, some) idea what it was, but I had an inkling that it might be worth trying.

Once I'd finished the inkling (which was delicious), I ran through the debugger again, and it worked. It seems that ForceInitialize() forces an initialise that would normally be forced when actually viewing the control for the first time.

[Tags: ]

24 August 2006

Visual Studio code definition window

Just found a handy Visual Studio thing: the code definition window. When looking through some code, this window shows the definition of the identifier under the cursor. I usually press F12 to go to the definition, and Ctrl- to go back again. Using the CDW, I get to see both at the same time!

To get to the CDW, use the view menu, or press Ctrl+W+D.

[Tags: ]

18 August 2006

Running MSTest from MSBuild

A while ago I wrote about running mstest.exe from MSBuild. I gave details of the MSBuild script, but not the utility to rewrite the file paths. Arundhati emailed me for some more details, so instead of emailing him the details, I thought I'd blog them.

The first step is to add a list of tests in Visual Studio, and move the tests into this list. Most of the source is here, but some of the simpler methods (like reading and writing the files) I'll leave out for brevity.

// Call this from Main, passing the args

public int ReplaceAbsolutePath(string[] args)

{

    // Ensure that an argument has been passed in, and the file exists

    if (IsArgumentValid(args) == false)

        return 1;

 

    // Load the file

    if (LoadTestConfigData() == false)

        return 1;

 

    // Replace the XML with the file's path

    if (ReplaceDirectoryName() == false)

        return 1;

 

    // Write the XML back to disk

    if (WriteXmlToFile() == false)

        return 1;

 

    // Success!

    return 0;

}



Choose the replacement method:

private const string testRunConfigExtension = ".testrunconfig";

private const string vsmdiExtension = ".vsmdi";

 

private bool ReplaceDirectoryName()

{

    // Compare the extension to see which time of replacement to do.

    FileInfo testConfigFile = new FileInfo(testConfigFileName);

    string extension = testConfigFile.Extension;

 

    // Depending on the file type, do the replacement

    if (extension == testRunConfigExtension)

        return ReplaceDirectoryForTestRunConfig();

    if (extension == vsmdiExtension)

        return ReplaceDirectoriesForVsmdi();

 

    // Should have returned by now.

    Console.WriteLine("Couldn't replace directory name");

    return false;

}



.vsmdi replacement:

private const string xpathLocalTestRunStorage = "/Tests/TestCategory/runConfiguration/storage";

private const string xpathAssemblyStorage = "/Tests/TestCategory/testLinks/value/storage";

private const string localTestRunFileName = @".\localtestrun.testconfig";

 

private bool ReplaceDirectoriesForVsmdi()

{

    // Replace the localtestrun.testrunconfig storage value with

    // a relative path.

    ReplaceNodeInnerText(xpathLocalTestRunStorage, localTestRunFileName);

 

    // Find all storage nodes in the XML

    XmlNodeList storageNodes = testConfigData.SelectNodes(xpathAssemblyStorage);

    // Loop through them, and set the correct absolute path.

    foreach (XmlNode storageNode in storageNodes)

    {

        if (GetDirectoryForVsmdi(storageNode) == false)

        {

            return false;

        }

    }

 

    return true;

}

 

private bool GetDirectoryForVsmdi(XmlNode node)

{

    try

    {

        // Get the directory currently used from the vsmdi file

        string currentAssembly = node.InnerText;

 

        string inputDirectory = GetInputDirectoryName().ToLower();

 

        // Find the lowest level directory of the vsmdi file location.

        string[] allDirectories = inputDirectory.Split('\\');

        string lowestDirectory = allDirectories[allDirectories.Length - 1];

 

        // Find this directory in the current setting, and note the position of the

        // end of the string.

        int stringPosition = currentAssembly.IndexOf(lowestDirectory) + lowestDirectory.Length;

 

        // Remove everything above (and including) this directory in the vsmdi directory name.

        currentAssembly = currentAssembly.Substring(stringPosition);

 

        // Add the current path root to the remainder of the assembly path.

        currentAssembly = inputDirectory + currentAssembly;

 

        // Replace the current node text with the new directory.

        node.InnerText = currentAssembly;

    }

    catch (Exception e)

    {

        Console.WriteLine(e.Message);

        Console.WriteLine(e.StackTrace);

        return false;

    }

    return true;

}



Replace the xml

private const string xpathRelativePathRoot = "/Tests/TestRunConfiguration/relativePathRoot";

 

private bool ReplaceDirectoryForTestRunConfig()

{

    return ReplaceNodeInnerText(xpathRelativePathRoot, GetInputDirectoryName());

}

 

private bool ReplaceNodeInnerText(string xpath, string newText)

{

    // Navigate to the relative path root node in the data file.

    XmlNode node = testConfigData.SelectSingleNode(xpath);

    if (node == null)

        Console.WriteLine("Couldn't find node: " + xpath);

    else

        // Replace the existing path with the new one.

        node.InnerText = newText;

    return true;

}

 

private string GetInputDirectoryName()

{

    // Get the directory from the XML filename.

    FileInfo testConfigFile = new FileInfo(testConfigFileName);

    string directoryName = testConfigFile.DirectoryName;

    return directoryName;

}



Hopefully this is enough to get you started.

[Tags: ]

17 August 2006

SourceSafe and branching in Visual Studio

Branching an entire solution in SourceSafe has a little gotcha. If you open the solution in Visual Studio, the solution file is bound to the branch in SourceSafe, but the contents of the solution file are unchanged. This means that the paths to the SourceSafe projects still refer to the "trunk", which can be mighty confusing. Fortunately, a workaround exists.

Open the branched solution in Visual Studio, and do File -> Source Control -> Change Source Control. Look at the server bindings. The solution file is bound correctly to the branched project, but the projects are bound to the trunk. For each of the projects, click "Unbind", reselect it (yes, the row changes after unbinding), and click bind. Select the correct project in the resultant dialog, and OK. The bindings are now correct, and you should be able to check in and out of the branch directly from Visual Studio.

All your projects are belong to us.

[Tags: ]

14 August 2006

Customer service, sales or marketing?

I was talking to someone I met at a wedding on Friday, who told me he "couldn't sell me water if my house was on fire". He gave an example. He is an engineer, who ended up in management, which involved sales. He was at someone's house with the aim of selling the lady a new vacuum cleaner. Instead, he took a look at her existing one, and made it work a lot better than it currently was. The lady was delighted, but he'd proved his point. He couldn't sell a vacuum cleaner to someone who needed a vacuum cleaner.

I told him I disagreed with his conclusion, but he didn't get it. I suspect that the lady was so pleased that not only would she always buy that brand of vacuum cleaner, but she would tell her friends about the wonderful salesman that actually fixed her old one instead of trying to flog her a new one. I think he did a great job of selling. It's all about word-of-mouth these days.

[Tags: ]

10 August 2006

LoaderLock was detected

Similar to the ContextSwitchDeadlock popup I had trouble with a couple of months back, I've recently been getting a "LoaderLock was detected" popup.

Attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.


The problem can be solved in the same way though, by switching off the MDA:

Debug -> Exceptions -> Managed Debug Assistants

and unchecking the LoaderLock item.

[Tags: ]

4 August 2006

The Joy of Test

It's been a week of testing. I spent most of the week setting up two PCs with the latest modules for the testers to hammer. It's generally working so far - a couple of biggies, but mostly cosmetics. I thought I'd be all distraught whenever a bug showed up, but I'm actually really pleased, as every one that's caught is one less that the customer gets to see. And the testers are so much better at it than me.

Interestingly, today I spent an hour testing another project - one I hadn't worked on. It was maddening! Some pages took ages, didn't find the data I was expecting, and the layout could have been better. See, I'm sounding like a tester - listing the problems. However, there was benefit on two levels. Firstly, I got to fill out a feedback form with my observations, which will be fed back into the product. Secondly, I got to experience a little glimpse of what it's like being a tester.

They're welcome to it. All respect to them, it's an important job, and they do it very well. I'm just glad I don't have to do it. I'll remember that hour every time I submit code to the testers in future!

[Tags: ]

2 August 2006

The crowd goes wild!

I'm not usually one to join in with memes, let alone start one, but now I'm going to attempt to: I want to know what your best coding moment was. The one where, had it been a spectator sport, the crowd would be screaming your name, throwing flowers, waving flags with your face on it and taking photos of your greatest moment.

All of us have great stories to tell, and achieved great things, often under high pressure or late at night, but generally nobody notices, or takes much of an interest. If someone does, then modesty dictates that you must say things like "I was just doing my job", "It wasn't hard, it was just a case of ..." or "Anyone could have done it". Well, I'm interested. I want to hear your war stories. It's time to be proud of what you've done. Get some recogition for your effort, skill, wisdom, cunning, and well, sheer brilliance. Big yourself up.

So, your best coding achievement please. Either leave a comment, or post to your own blog and link here.