Anything related to the .NET framework
23 Apr 2010

Find Results Tweak - Now with less suck

extensionmanager I posted the other day about a Visual Studio add-in which I developed. When developing it, I used the add-in model which has a nasty side effect, it needs to be installed with a MSI. Visual Studio 2010 can also be extended with packages and these can be deployed using the VSIX format.

What is this magical new VSIX format? It is basically a ZIP file which contains everything you need plus a manifest which tells VS how to use it. What makes this much better is that VS handles the install itself, so no MSI is needed. It is also then listed in the Extension Manager and so can take advantage of the features there by being disabled/uninstalled easily, not that you would want to.

A great side effect of this is that the new extension model let me add a little more error handling to the tool to help out debugging it. To get the new version go to http://findresultstweak.codeplex.com

20 Apr 2010

Tweaking the Find Results window in Visual Studio 2010

Visual Studio is filled with goodness and happiness and a lot of that is available for tweaking, so you can get the maximum goodness, via the Tool -> Options menu. One of the things which doesn’t have any visible options is the formatting of the way the results are displayed:

findresults1

The problem, as indicated above, is a ton of white space, long file paths, no column information etc… Wouldn’t it be great to tweak how that can be displayed? Thankfully Sara Ford found a way to do exactly that via the registry. So you could tweak it to actually display the way you want it!

findresults2

In my tweaked way it is far more condense with just the filename (no more path), less whitespace (since I am showing only a summary of results) and I also included the column info. The problem is that editing the registry is not user friendly :( This gave me a chance to write my first Visual Studio add-in, which gives you an option inside Visual Studio to set it.

usage2

What is really nice is that while you configure the format, the preview window will update and show you how it looks so you do not get any surprises when you save it! If you would like to find out more about it you can go to the site on CodePlex at http://findresultstweak.codeplex.com/

12 Apr 2010

Installing TFS 2010 Basic on a Laptop

I decided that I would like show how easy it is to install TFS 2010 on a laptop in an upcoming presentation, but I also want to use that TFS installation for demo’s which is a worry – what happens if the install fails? So what I decided to do was create a video of me installing TFS, this way I can show the video and not worry about my demos not working because of some demo failure. As I am such as nice guy, I decided to share it with everyone on YouTube, so here is the video:

16 Mar 2010

Reading and writing to Excel 2007 or Excel 2010 from C# - Part V: Full source for reading

[Note: See the series index for a list of all parts in this series.]

Clipboard08

A few people have battled with getting all the bits of code scattered in the series together to actually work. This is not only due to the fact they are scattered, but part III for example was not showing the code correctly and there was a bug in part IV. I have gone back and fixed those issues and to help further here is the full code in one big view (click read more if needed to see it).

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

namespace ReadFromExcel
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Cell> parsedCells = new List<Cell>();
            string fileName = @"C:\Users\bbdnet0758\Desktop\Demo.xlsx";
            Package xlsxPackage = Package.Open(fileName, FileMode.Open, FileAccess.ReadWrite);
            try
            {
                PackagePartCollection allParts = xlsxPackage.GetParts();

                PackagePart sharedStringsPart = (from part in allParts
                                                 where part.ContentType.Equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml")
                                                 select part).Single();
                
                XElement sharedStringsElement = XElement.Load(XmlReader.Create(sharedStringsPart.GetStream()));

                Dictionary<int, string> sharedStrings = new Dictionary<int, string>();
                ParseSharedStrings(sharedStringsElement, sharedStrings);                

                XElement worksheetElement = GetWorksheet(1, allParts);

                IEnumerable<XElement> cells = from c in worksheetElement.Descendants(ExcelNamespaces.excelNamespace + "c")
                                              select c;

                foreach (XElement cell in cells)
                {
                    string cellPosition = cell.Attribute("r").Value;
                    int index = IndexOfNumber(cellPosition);
                    string column = cellPosition.Substring(0, index);
                    int row = Convert.ToInt32(cellPosition.Substring(index, cellPosition.Length - index));
                    int valueIndex = Convert.ToInt32(cell.Descendants(ExcelNamespaces.excelNamespace + "v").Single().Value);

                    parsedCells.Add(new Cell(column, row, sharedStrings[valueIndex]));
                }
            }
            finally
            {
                xlsxPackage.Close();
            }

            //From here is additional code not covered in the posts, just to show it works
            foreach (Cell cell in parsedCells)
            {
                Console.WriteLine(cell);
            }
        }

        private static void ParseSharedStrings(XElement SharedStringsElement, Dictionary<int, string> sharedStrings)
        {
            IEnumerable<XElement> sharedStringsElements = from s in SharedStringsElement.Descendants(ExcelNamespaces.excelNamespace + "t")
                                                          select s;

            int Counter = 0;
            foreach (XElement sharedString in sharedStringsElements)
            {
                sharedStrings.Add(Counter, sharedString.Value);
                Counter++;
            }
        }

        private static XElement GetWorksheet(int worksheetID, PackagePartCollection allParts)
        {
            PackagePart worksheetPart = (from part in allParts
                                         where part.Uri.OriginalString.Equals(String.Format("/xl/worksheets/sheet{0}.xml", worksheetID))
                                         select part).Single();

            return XElement.Load(XmlReader.Create(worksheetPart.GetStream()));
        }

        private static int IndexOfNumber(string value)
        {
            for (int counter = 0; counter < value.Length; counter++)
            {
                if (char.IsNumber(value[counter]))
                {
                    return counter;
                }
            }

            return 0;
        }                         
    }

    internal static class ExcelNamespaces
    {
        internal static XNamespace excelNamespace = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
        internal static XNamespace excelRelationshipsNamepace = XNamespace.Get("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
    }

    public class Cell
    {
        public Cell(string column, int row, string data)
        {
            this.Column = column;
            this.Row = row;
            this.Data = data;
        }

        public override string ToString()
        {
            return string.Format("{0}:{1} - {2}", Row, Column, Data);
        }

        public string Column { get; set; }
        public int Row { get; set; }
        public string Data { get; set; }
    }
}
14 Jan 2010

Holy download fever Batman

Seems that in the last week, and just in time for me to be in Canada where they have bandwidth, that a bunch of things have become available for download which deserve your attention:

VS 2010 Quick Reference Guidance is now out!

Plus hotfix 1 for it

Visual Studio Team Foundation Server 2010 Upgrade Guidance is now out!

The new Nokia 5800 firmware (40.0.0.5) is out – which brings it up to the level of the X6 in features now!

Lastly, and sneakily at the end of this post, my latest open source tool is out. Now I am not going to tell you what it is, but it is for presenters (mostly) and requires .NET 4.0 Beta 2 and Windows 7. Hopefully the name will entice you to check out Rule 18!

05 Jan 2010

Inline methods with ThreadPool and WaitCallback

Slightly for my own memory (since I will forget in future and at least it's available here), but for an upcoming training session which I am presenting, I wanted to be able to inline a method when using the .NET ThreadPool’s QueueUserWorkItem method which requires a WaitCallback pointing to a method. I did this using the lambda expression support in .NET 3.0+ and it looks like this:

static void Main(string[] args)
{
    Console.WriteLine("Starting up");

    ThreadPool.QueueUserWorkItem(new WaitCallback(f =>
    {
        Console.WriteLine("Hello for thread");
        Thread.Sleep(500);
        Console.WriteLine("Bye from thread");
    }));

    Console.ReadKey();
}
04 Jan 2010

StackOverflow with ListBox or ListView

Clipboard013 I have been writing some multi-threaded code recently where I was initially adding items to the .NET ListBox control and then later changed to the ListView control. In both cases my code I would get a StackOverflow exception fairly consistently when I added the 224th item (my first two items I added manually so it was the 222nd item added via a separate thread). The first troubleshooting tip is that you do not have an infinite loop, which I could confirm that it did not have.

So the first thing I tried, was to limit the number of items which would be added with each button click. Doing this enabled me to go well over the 224/222 limit from before – thus eliminating any thoughts of limit on the number of items the controls could handle.

After some other failed tests I found out it was how I was handling the cross thread communication, being that I had a separate thread add the items to the control which was created on the applications main thread. To handle to cross threaded communication I kept calling this.BeginInvoke, however I never called this.EndInvoke which a lot of places seem to say it is fine. However at some point it will fail, with the StackOverflow exception – that point is dependant on a number of factors (including the worst factor of all: timing, making this one of those issues that may only appear in the field).

My solution was simple, change the standard this.Invoke method and the issue went away.

For the search engines the full exception is “An unhandled exception of type 'System.StackOverflowException' occurred in System.Windows.Forms.dll”.

Pages