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:
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.]
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; } } }
Reading and Writing to Excel 2007 or Excel 2010 from C# - Series Index
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!
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(); }
StackOverflow with ListBox or ListView
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”.
Most Valuable Indian
So yesterday I posted about myself getting the MVP award, well today it got better as my friend, co-worker, fellow VSTS Ranger and S.A. Architect lead: Zayd Kara has also been awarded a MVP for his work with Team System! Congratulations Zayd!
And the award goes to...

With the count down clock at T-10 days to my sabbatical trip an email popped into my mail box… it was an email from Microsoft congratulating me on getting the MVP (Most Valuable Professional) award for my work with Team System!
What is this MVP Award?
The Microsoft MVP Award is an annual award that recognizes exceptional technology community leaders worldwide who actively share their high quality, real world expertise with users and Microsoft… With fewer than 5,000 awardees worldwide, Microsoft MVPs represent a highly select group of experts. MVPs share a deep commitment to community and a willingness to help others. They represent the diversity of today’s technical communities. MVPs are present in over 90 countries, spanning more than 30 languages, and over 90 Microsoft technologies. MVPs share a passion for technology, a willingness to help others, and a commitment to community. These are the qualities that make MVPs exceptional community leaders. MVPs’ efforts enhance people’s lives and contribute to our industry’s success in many ways. By sharing their knowledge and experiences, and providing objective feedback, they help people solve problems and discover new capabilities every day. MVPs are technology’s best and brightest…
Richard Kaplin, Microsoft Corporate Vice President
So this is a great honour for me to be welcomed into a group of people who I look up to and respect :) You can see my new MVP profile up at https://mvp.support.microsoft.com/profile/Robert.MacLean
Presentation Data Dump
Over the last year I have done a number of presentations and recently some of uploaded them (unfortunately I cannot upload all, as some contain NDA information) to SlideShare so here is the collection of presentations from the last 15 months or so, in no particular order:
- ASP.NET Dynamic Data
- JSON and REST
- What’s Microsoft CRM all about?
- Source Control 101
- SQL Server Integration Services
- ASP.NET MVC
- What’s new in the .NET Framework 3.5 SP 1
Click the read more link to see and download them...
ASP.NET Dynamic Data
JSON and REST
What’s Microsoft CRM all about?
Source Control 101
SQL Server Integration Services
ASP.NET MVC
What’s new in the .NET Framework 3.5 SP 1
Dev4Devs - 28 November 2009
Well today is the day! Dev4Dev’s is happening at Microsoft this morning and I will be speaking on 10 12 new features in the Visual Studio 2010 IDE. For anyone wanting the slide deck and demo application I used you can grab them below.
The slide deck is more than the 6 visible slides, there is in fact 19 slides which cover the various demos and have more information on them so you too can present this to family and friends :)