Andrew Coates ::: MSFT

It's all about community!

  • Andrew Coates ::: MSFT

    August 2011 Windows Azure Releases


    While I was overseas, the Windows Azure team announced the availability of the

    Grab 'em while they're, if not hot then at least luke warm.

  • Andrew Coates ::: MSFT

    TechEd Australia Session Recordings and Decks


    Update 4 Sep 2011 - The videos and slides are beginning to appear on the Channel 9 TechEd Australia 2011 Site.

    Once again we've captured all of the main track sessions from TechEd Australia this year. We grabbed whatever video went to the screen and whatever audio went to the speakers. This means we've got almost 170 75-minute sessions to do the following to:

    1. Edit the files to remove the extra time at the beginning and the end then re-encode
    2. Upload the 200+ MB file to an Azure blob
    3. Process the high quality file to produce about 5 other formats including audio only, a couple of MP4 versions, at least one more WMV and some jpg thumbnails, as well as a smooth-streaming version
    4. Upload the slides to the an Azure blob
    5. Create the landing page for each session which will allow you to view the session and/or download any or all of the formats in 3 and 4 above (linked from

    As of right now, numbers 1 and 4 are complete. Number 2 is about 10% done, number 3 is yet to start and while the pages are up (5), there's not yet a link to even the slides. Of course, if you were at TechEd Australia, you can log into the Schedule Builder and download slides from there.

    I'll keep this blog updated every once in a while with the progress of things.

  • Andrew Coates ::: MSFT

    TechEd Australia LightSwitch Decks and Resources


    My TechEd Australia sessions proved to be pretty popular and I had a great time catching up with people afterwards.

    The number 1 resource you need for LightSwitch is

    Here are the decks:

    Introduction to Visual Studio LightSwitch DEV201

    Advanced Solutions with Visual Studio® LightSwitch™ DEV213

  • Andrew Coates ::: MSFT

    LightSwitch Decks from TechEd NZ


    I presented two sessions at TechEd NZ last week and I've attached the decks here for anyone who's interested.

    Introducing Visual Studio LightSwitch DEV203

    Visual Studio LightSwitch Beyond the Basics DEV308

  • Andrew Coates ::: MSFT

    Windows Azure Toolkit for Social Games & Tankster Version 1.0 | Nathan Totten


    This looks like it could be a lot of fun. I think I've figured out what my son and I are going to do in our spare time for the next little while.

    Windows Azure Toolkit for Social Games & Tankster Version 1.0 | Nathan Totten

  • Andrew Coates ::: MSFT

    Document Creation and Conversion with the OpenXML SDK and SharePoint 2010 Word Automation Services – Part 2


    A long time ago, I wrote Part 1 of this post, based on the presentation I did at the 2010 SharePoint Conference in Sydney. If you're following along with the code, you may want to review that post so you can set up your development environment to match mine.

    To quickly recap, the last post showed how to create Word (OpenXML, docx) documents programmatically and write them to disk using the OpenXML SDK (and therefore without the requirement for Word/Office on the machine creating the documents).

    In this part, I'll extend the solution to write the documents to a document library in SharePoint and then use Word Automation Services to automatically convert the docx files to PDF format.


    To follow along with this walkthrough without changes, setup your SharePoint instance (at http://localhost) as follows:

    • Create a document library called "Created Docs" in the root site
    • Create a document library called "Converted Docs" in the root site

    If you use a remote server, and/or a different site or library names, you'll need to adjust some of the URI and path strings in the code below to make it work.

    Writing to a SharePoint Library

    Carrying on from last time, wire up the click event of the CreateOneSharePointDocumentButton:

    Click event handler
    1. private void CreateOneDocumentOnSharePointButton_Click(object sender, EventArgs e)
    2. {
    3.     gen.CreateOneDocumentOnSharePoint();
    4. }

    Generate a stub for the CreateOneDocumentOnSharePoint() method in the DocGenerator class using the Ctrl+. technique made possible by the Visual Studio 2010 Productivity Power Tools.

    Switch to and add a using statement to the DocGenerator class to give you access to the SharePoint Client Libraries - giving it an alias will help disambiguate the File class later:

    1. using SPC = Microsoft.SharePoint.Client;

    Using the SharePoint Client Libraries, it's very easy to write documents to a document library, and there's no need to write a document to a local drive. This means we'll use a different overload of the OpenXML SDK's WordprocessingDocument.Create() method that writes, not to a file, but to a MemoryStream.

    1. internal void CreateOneDocumentOnSharePoint()
    2. {
    3.   SPC.ClientContext clientContext = new SPC.ClientContext("http://localhost");
    4.   string fileUrl = "/Created Docs/MyVeryVeryCoolDoc.docx";
    6.   sw.Reset();
    7.   sw.Start();
    9.   using (MemoryStream ms = gen.CreatePackage())
    10.   {
    11.     ms.Seek(0, SeekOrigin.Begin);
    12.     SPC.File.SaveBinaryDirect(clientContext, fileUrl, ms, true);
    13.   }

    In this code, you create a new SharePoint.Client.ClientContext that gives access to the site (in this case at http://localhost, but if you've got things set up differently, change it here).

    Create an overload of the CreatePackage() method in the DocumentCreator class that creates and populates a MemoryStream:

    CreatPackage Overload
    1. internal MemoryStream CreatePackage()
    2. {
    4.   MemoryStream ms = new MemoryStream();
    5.   using (WordprocessingDocument package =
    6.     WordprocessingDocument.Create
    7.     (ms, WordprocessingDocumentType.Document))
    8.   {
    9.     CreateParts(package);
    10.   }
    12.   return ms;
    14. }

    Move the pointer to the start of the MemoryStream and call the File.SaveBinaryDirect() method passing in the ClientContext, a string indicating where the file should be written, the stream and a boolean that tells SharePoint whether or not to overwrite an existing file with the same name.

    Running the app and clicking the One document in SharePoint button shows that it's very fast - in my case 102ms

    Writing 1 document to SharePoint took 0.1 seconds

    Writing lots of documents is fast too - add an event handler to the CreateOneSharePointDocumentButton:

    Click Event Handler
    1. private void CreateManyDocumentsOnSharePointButton_Click(object sender, EventArgs e)
    2. {
    3.   gen.CreateManyDocumentsOnSharePointInParallel((int)NumberOfDocumentsToCreate.Value);
    5. }

    And add a CreateManyDocumentsOnSharePointInParallel() method that uses a Parallel.For() loop to call CreatePackage() and File.SaveBinaryDirect() for as many files as you create:

    Create lots of SharePoint Docs
    1. internal void CreateManyDocumentsOnSharePointInParallel(int NumberOfDocs)
    2. {
    3.   SPC.ClientContext clientContext = new SPC.ClientContext("http://localhost");
    4.   string fileUrl = "/Created Docs/MyEvenCoolerDoc{0:D5}.docx";
    6.   sw.Reset();
    7.   sw.Start();
    9.   Parallel.For(0, NumberOfDocs, i =>
    10.   {
    12.     using (MemoryStream ms = gen.CreatePackage())
    13.     {
    14.       ms.Seek(0, SeekOrigin.Begin);
    15.       SPC.File.SaveBinaryDirect(clientContext, string.Format(fileUrl, i), ms, true);
    16.     }
    18.   });
    20.   sw.Stop();
    22.   System.Windows.Forms.MessageBox.Show(string.Format(
    23.       "Wrote {3} documents to SharePoint ({1}{2}) in {0} ms (using parallel processing)",
    24.       sw.ElapsedMilliseconds,
    25.       clientContext.Url,
    26.       fileUrl,
    27.       NumberOfDocs));
    29. }

    This is also pretty fast - in my case 40ms per document.

    Writing 100 documents to SharePoint (in parallel) took 4 seconds

    Navigating to the document library shows all those documents sitting just where you'd expect to see them:

    Cool documents created en-masse

    Converting Word Documents to a Fixed Format (PDF or XPS)

    PDFUp until now, we've not had to use Word (or any other Office client) as all we've been doing is generating documents, not rendering them. Just like you can create an HTML document without requiring a browser, it's perfectly valid to create a Word document (or any other OpenXML format document) without using Word.

    However, to view the document, or to create a fixed version of it like PDF or XPS, it's necessary to render it. Up until the release of SharePoint 2010, the highest fidelity way to do this was to open the document in Word. Of course, doing that on the server was fraught with difficulty. Word is not designed to be a server-side tool - it throws (sometimes modal) dialogs, it spends a lot of resources on updating the screen and it's not optimised for multi-processor, large memory scenarios. When there is a user interacting with Word though, the bottleneck is rarely the computer.

    The SharePoint team addressed this problem with the Word Automation Services feature in SharePoint 2010 (standard edition and higher). Word Automation Services is the client code from Word with the UI bits stripped out and optimised to run as a server process. All of the rendering engine is available for SharePoint to use without any of the issues (both technical and from a licensing point of view) of using Word on a server. There's lots of great info on Word Automation Services on MSDN and elsewhere. Here's the list of resources I provided in the first post in this series:

    Word Automation Services (WAS) document conversion jobs run as as an asynchronous server-side job that can either be scheduled automatically (for example, when a document is placed in a folder) or programmatically. Either way, the job won't start immediately, just the next time the WAS scheduler runs. The frequency of the scheduler running is set in Central Administration - see the links above for details on how to set it up. I set it to the minimum interval - one minute.

    Interacting programmatically with the service is pretty straightforward, but there are two gotchas:

    1. the .NET libraries are 3.5 only, so the project you create must be a .NET 3.5 project, and
    2. the calls will fail (with cryptic exceptions) if it's not a 64-bit call, so you must target either x64 or Any processor type, not x86.

    Create a new console application and make sure that the target framework is 3.5.

    Create a new console application targetting Framework 3.5

    Open the Visual Studio Configuration Manager dialog by dropping down the Solution Configurations drop-down on the Visual Studio Standard toolbar (or choosing Configuration Manager from the Build menu):

    Choose Configuration Manager

    Next, add a Solution Platform:


    to target Any CPU (or x64)


    Now you're ready to start building.

    Converting a single document to PDF

    Add references to the Microsoft.SharePoint and Microsoft.Office.Word.Server assemblies.

    Add using statements for those assemblies:

    1. using Microsoft.SharePoint;
    2. using Microsoft.Office.Word.Server.Conversions;

    Add a couple of static string properties to the class that you can adjust to suit the way you've got your SharePoint setup configured:

    1. // If you manually installed Word Automation Services, then replace the name
    2. // in the following line with the name that you assigned to the service when
    3. // you installed it.
    4. static string cWordServicesName = "Word Automation Services";
    5. static string siteUrl = "http://localhost";

    Now you can initiate the conversion of a single document:

    Convert a single document
    1. private static void SingleConv()
    2. {
    3.   using (SPSite spSite = new SPSite(siteUrl))
    4.   {
    5.     ConversionJob job = new ConversionJob(cWordServicesName);
    6.     job.UserToken = spSite.UserToken;
    7.     job.Settings.UpdateFields = true;
    8.     job.Settings.OutputFormat = SaveFormat.PDF;
    9.     job.AddFile(siteUrl + "/Created%20Docs/MyAwesomeDoc.docx",
    10.         siteUrl + "/Converted%20Docs/MyAwesomeDoc.pdf");
    11.     job.Start();
    12.     Console.WriteLine("Job ID: {0} started", job.JobId);
    13.     Console.WriteLine("Press the any key ...");
    14.     Console.ReadKey();
    15.   }
    16. }

    There are a few things to note here.

    Firstly, you get a reference to the Site using the SharePoint libraries, not the SharePoint Client libraries that we used to write the Word docs to the list in the first place.

    Next, you need to pass a user token to the new ConversionJob, and you get that from the SPSite user token.

    Third, you specify the output format using the SaveFormat enumeration.

    Finally, remember the service is performed asynchronously and so although you get a Job ID back, you don't get any more information about the job status (more on that when we do bulk conversions)

    Converting documents to PDF en-masse

    Converting whole libraries at once is also very easy. The ConversionJob class has an AddLibrary() method that takes as parameters a source and destination SPList object.

    Converting whole libraries
    1. private static void BulkConv()
    2. {
    3.   using (SPSite spSite = new SPSite(siteUrl))
    4.   {
    5.     Console.WriteLine("Starting conversion job");
    6.     ConversionJob job = new ConversionJob(cWordServicesName);
    7.     job.UserToken = spSite.UserToken;
    8.     job.Settings.UpdateFields = true;
    9.     job.Settings.OutputFormat = SaveFormat.PDF;
    10.     job.Settings.OutputSaveBehavior = SaveBehavior.AlwaysOverwrite;
    11.     SPList listToConvert = spSite.RootWeb.Lists["Created Docs"];
    12.     SPList listToPopulate = spSite.RootWeb.Lists["Converted Docs"];
    13.     job.AddLibrary(listToConvert, listToPopulate);
    14.     job.Start();
    15.     Console.WriteLine("Bulk conversion job {0} started", job.JobId);
    16.     ConversionJobStatus status = new ConversionJobStatus(cWordServicesName,
    17.         job.JobId, null);
    18.     Console.WriteLine("Number of documents in conversion job: {0}", status.Count);
    19.     while (true)
    20.     {
    21.       System.Threading.Thread.Sleep(5000);
    23.       status.Refresh();
    24.       if (status.Count == status.Succeeded + status.Failed)
    25.       {
    26.         Console.WriteLine("{2} Completed, Successful: {0}, Failed: {1}",
    27.             status.Succeeded, status.Failed, DateTime.Now);
    28.         break;
    29.       }
    30.       Console.WriteLine("{2} In progress, Successful: {0}, Failed: {1}",
    31.           status.Succeeded, status.Failed, DateTime.Now);
    32.     }
    34.     Console.ReadKey();
    35.   }
    36. }

    Checking the status of the job is straightforward (as long as you have the JobId - a GUID uniquely identifying this conversion job). The ConversionJobStatus object holds information about the conversion job including how many documents are to be converted, how many have been converted successfully and how many have failed. Calling the Refresh() method gets the most up-to-date status and you can use that to poll for completion. Remember that jobs only start every <n> minutes, where n is a setting in SharePoint Central Administration

    Converting documents is an asynchronous process

    The result is a SharePoint list full of PDF files, created without ever needing to open Word.

    A library full of converted PDFs

    A converted PDF in Adobe Reader


    The combination of the OpenXML SDK and Word Automation Services makes server-side document creation simple, scalable and efficient. This is definitely a tool worth adding to your arsenal.

    Source Code

    I've zipped up the two solutions - the document creation (.NET 4.0) WinForms project and the document conversion (.NET3.5) project for you to download and play with. Notice that they are NOT production ready - they're illustrative only. Use them at your peril, your mileage may vary, contents may be hot no guarantees etc … you know the drill.

    Document Creation Solution Download (241kB)
    Document Conversion Solution Download (115kB)

  • Andrew Coates ::: MSFT

    Counting the number of sections in an OpenXML Document


    1/4/11 - Updated a couple of images and some of the code explanation

    Adam Cogan asked me a question the other day that asked (among other things) "How do you know if a doc has multiple sections?"

    In Word, of course, you can break a document up into sections by inserting a section  break from the Breaks button in the Page Setup group on the Page Layout tab:

    Inserting section breaks manually in Word is easy

    It turns out that counting these programmatically is really easy using the OpenXML SDK 2.0 (download)

    I created a new console application, added a reference to DocumentFormat.OpenXML and WindowsBase and used this code:

    Count Sections in Word Docx
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.IO.Packaging;
    6. using DocumentFormat.OpenXml.Wordprocessing;
    7. using DocumentFormat.OpenXml.Packaging;
    8. using DocumentFormat.OpenXml.Office2010.Word;
    10. namespace CountSections
    11. {
    12.   class Program
    13.   {
    14.     static void Main(string[] args)
    15.     {
    16.       if (args.Length != 1)
    17.       {
    18.         Console.WriteLine("Usage: CountSections <filename>");
    19.       }
    20.       else
    21.       {
    22.         using (WordprocessingDocument d =
    23.             WordprocessingDocument.Open(args[0], false))
    24.         {
    25.           Console.WriteLine("Found {0} section(s)",
    26.               d.MainDocumentPart.Document.Body.Descendants().
    27.               OfType<SectionProperties>().Count()
    28.               );
    29.         }
    30.         Console.WriteLine("Press any key ...");
    31.         Console.ReadKey();
    32.       }
    33.     }
    34.   }
    35. }

    In it I take the filename passed as an argument and open it ReadOnly (line 22-23). I then find the number of sections using the typed enumerator (lines 26-27)

    I also added the path to a file in the Command Line Arguments edit box in the Debug tab of the project Properties so there's a file being passed in when I press F5:

    Pass a file name in as a command line argument

    Running the program gives the answer very quickly:

    Resulting output - we found 2 sections

    Cool huh?

    Sample file with 2 sections Download

  • Andrew Coates ::: MSFT

    Storytelling - A Moth-eaten theme


    One of the most effective ways to get a message, any message, across is to use stories. For some reason the human brain appears to be wired to be good at remembering and regurgitating stories. I like to begin presentations with a story that’s somehow relevant and am always on the lookout for a good story to add to my repertoire.

    The best stories seem to be those told from a personal perspective - either something that happened to you or something you witnessed. Good stories also stir emotions, both in the storyteller and the listener.

    The MothThis week I heard two stories that did just that. I’ve been a listener to the Moth Podcast for some time now, and have always enjoyed the mix of professional storytelling with deeply personal and evocative content. Two of the stories I heard this week though moved me as much or more than any other I’ve heard.

    The first, told by a comedian, wasn’t funny. The second, told by someone who plays the blues, was uplifting. Both made either made me laugh or cry - literally out loud.

    Listen to

    and then tell me whether you experienced the same thing.

    While you’re there, subscribe to the Moth podcast either in iTunes or via their RSS feed.

  • Andrew Coates ::: MSFT

    More VSS to TFS Workshops this Month in MEL, SYD, BNE and Online


    VSS to TFS Workshops

    Hot on the heels of my post on the Readify DevDay in Sydney, I got a note about even more VSS to TFS workshops (this time presented by Richard Angus from Enhance ALM).

    Topics include:

    • The benefits of migrating to TFS
    • A demonstration of the key features of TFS
    • Pre-migration planning
    • Hands-on walk through of the migration process
    • Verifying our migration and troubleshooting common issues

    Dates and locations

    Date Location Registration Link
    11 April (2 sessions) Melbourne Register
    12 April (2 sessions) Sydney Register
    13 April (2 sessions) Brisbane Register
    21 April Online Live Meeting Register
  • Andrew Coates ::: MSFT

    TFS for VSS Users - 1/2 day training in Sydney


    I got this note from Sarah Webb at Readify today - looks like a good way to spend half a day if you’re looking to move from Visual Source Safe to a more modern source control system (and get a heap of additional goodness thrown in)

    Readify Dev Day:

    TFS for VSS Users…

    Since 2005, Team Foundation Server (TFS) has been providing integrated version control, work management and build capabilities. The release of TFS 2010 builds on the foundations formed in the earlier 2005 and 2008 products and focuses on lowering the barrier of entry for teams wanting to get the maximum benefit from TFS with minimal implementation fuss.

    Come along to this half day RDN Dev Day event to learn what is involved in getting TFS up and running in your development team. Presented by Readify Senior Consultant and Visual Studio ALM MVP, Stephen Godbold.


    During this session, Stephen will be covering:

    • What you need to know to deploy and utilise the basic functions of TFS including how to implement version control, build and work management.
    • The roadmap of what greater deployment/integration will bring, along with the business value this delivers.
    • A look at the migration path from Visual Source Safe to Team Foundation Server.


    Date: Friday 29 April 2011

    Location: Cliftons | 190 George Street, SYDNEY

    Duration: Half Day (including light refreshments)

    Times: AM Session: 9am – 12pm OR PM Session: 2pm – 5pm

    For more information, and to register, go to the Readify site.

Page 6 of 48 (472 items) «45678»