The blogs of Black Marble staff

Swapping the the Word template in a VSTO project

We have recently swapped the Word template we use to make sure all our proposals and other documents are consistent. The changes are all cosmetic, fonts, footers etc. to match our new website; it still makes use of the same VSTO automation to do much of the work. The problem was I needed to swap the .DOTX file within the VSTO Word Add-in project, we had not been editing the old DOTX template in the project, but had created a new one based on a copy outside of Visual Studio.

To swap in the new .DOTX file for the VSTO project I had to...

  • Copy the new TEMPLATE2014.DOTX file to project folder
  • Opened the VSTO Word add-in .CSPROJ file on a text editor and replaced all the occurrences of the old template name with the new e.g. TEMPLATE.DOTX for TEMPLATE2014.DOTX
  • Reload the project in Visual Studio 2013, should be no errors and the new template is listed in place of the old
  • However, when I tried to compile the project I got a DocumentAlreadyCustomizedException. I did not know, but the template in the VSTO project needs to a copy with no association with any VSTO automation. The automation links are applied during the build process, makes sense when you think about it. As we had edited a copy of our old template, outside of Visual Studio, our copy already had the old automation links embedded. These needed to be removed, the fix was to
    • Open the .DOTX file in Word
    • On the File menu > Info > Right click on Properties (top right) to get the advanced list of properties

    • Delete the _AssemblyName and _AssemblyLocation custom properties
    • Save the template
    • Open the VSTO project in Visual Studio and the you should be able to build the project
  • The only other thing I had to do was make sure my VSTO project was the start-up project for the solution. Once this was done I could F5/Debug the template VSTO combination

5 Tips for using Azure Web Jobs

1. Use public on the main program class.In order for web jobs to initialise correctly the main class that contains the web jobs needs to be made public. Once this has been added the individual jobs can then be read and should be visible in the output when running locally.


2. In order to store and view the invocation details for each web job you need to configure AzureWebJobsDashboard in the configure tab of the website you have deployed the web job to. Even if you have configured this in your app.config file.


If this is not configured in the website then you will receive the following error when you try and view the web jobs dashboard


3. Debug using Visual Studio. Once of the nice features of the web jobs SDK is the ability to run and debug the web job locally in Visual Studio. Following the Getting Started guide, you create a console application which you can debug in Visual Studio before deploying it to Azure

4. User TextWriter for debugging. The Azure Web Jobs SDK (see the logging section) provides a mechanism to log out information that can be viewed through the Azure Web jobs dashboard. By adding a TextWriter as an input parameter to your web job method, you can use WriteLine to then output information you wish to log.

5. Make your Blob Triggers more efficient by triggering them using BlobOutput. The mechanism that the BlobInput trigger uses has a 10-20 minute lag before the trigger can fire, but each time BlobOutput is used it triggers a rescan for Blob input.

“There is an optimization where any blob written via a [BlobOutput] (as opposed to being written by some external source) will optimistically check for any matching [BlobInputs],” See How does [BlobInput] work?. Storage Queues and Service Bus topics and Queues are generally processed within seconds so if you can use a queue to trigger a BlobOutput then use this to trigger any subsequent BlobInputs

Using MSDEPLOY from Release Management to deploy Azure web sites

Whilst developing our new set of websites we have been using MSDeploy to package up the websites for deployment to test and production Azure accounts. These deployments were being triggered directly using Visual Studio. Now we know this is not best practice, you don’t want developers shipping to production from their development PCs, so I have been getting around to migrating these projects to Release Management.

I wanted to minimise change, as we like MSDeploy, I just wanted to pass the extra parameters to allow a remote deployment as opposed to a local one using the built in WebDeploy component in Release Management

To do this I created a new component based on the WebDeploy tool. I then altered the arguments to

__WebAppName__.deploy.cmd /y /m:__PublishUrl__" -allowUntrusted /u:"__PublishUser__" /p:"__PublishPassword__" /a:Basic


With these three extra publish parameters I can target the deployment to an Azure instance, assuming WebDeploy is installed on the VM running the Release Management deployment client.

The required values for these parameters can be obtained from the .PublishSettings you download from your Azure web site’s management page. If you open this file in a text editor you can read the values need (bits you need are highlighted in yellow)

<publishData><publishProfile profileName="SomeSite - Web Deploy" publishMethod="MSDeploy" publishUrl="" msdeploySite="SomeSite" userName="$SomeSite" userPWD="m1234567890abcdefghijklmnopqrstu" destinationAppUrl= SQLServerDBConnectionString="" mySQLDBConnectionString="" hostingProviderForumLink="" controlPanelLink=""><databases/></publishProfile><publishProfile profileName="SomeSite- FTP" publishMethod="FTP" publishUrl= ftpPassiveMode="True" userName="SomeSite\$SomeSite" userPWD=”m1234567890abcdefghijklmnopqrstu" destinationAppUrl= SQLServerDBConnectionString="" mySQLDBConnectionString="" hostingProviderForumLink="" controlPanelLink=""><databases/></publishProfile></publishData>

These values are used as follows

  • WebAppName – This is the name of the MSDeploy package, this is exactly the same as a standard WebDeploy component.
  • PublishUrl - We need to add the https and the .axd to the start and end of the url e.g:
  • PublishUser – e.g:  $SomeSite
  • PublishPassword – This is set as an encrypted parameter  so it cannot be viewed in the Release Management client e.g: m1234567890abcdefghijklmnopqrstu

On top of these parameters, we can still pass in extra parameters to transform the web.config using the setparameters.xml file as detailed in this other post  this allowing to complete the steps we need to do the configuration for the various environments in our pipeline.

Speaking at PreEmptive’s event on Application Analytics in London on the 30th of September

I am speaking at PreEmptive’s event on Application Analytics in at Microsoft’s office in London on the 30th of September. There are various speakers from PreEmptive, Microsoft and Black Marble at this free event.

There are still spaces available, just follow the link: Application Analytics with Visual Studio and PreEmptive Analytics for  more details and registration.

“Communication with the deployer was lost during deployment” error with Release Management

Whilst developing  a new Release Management pipeline I did hit a problem that a component that published MSDeploy packages to Azure started to fail.  It had been working then suddenly I started seeing ‘communication with the deployer was lost during deployment’ messages as shown below.



No errors were shown in any logs I could find, and no files appeared on the deployment target (you would expect the files/scripts to be deployed to appear on the machine running a RM Deployment client in the C:\users\[account]\local\temp\RM folder structure).

Rebooting of the Release Management server and deployment client had no effect.

The client in this case was a VM we use to do remote deployments e.g to Azure, SQL clusters etc. Place where we cannot install the RM Deployment Client. So it is used for a number of other pipelines, these were all working, so I doubted it was a communications issue.

In the end, out of frustration, I tried re-adding the component to the workflow and re-entering the parameters. Once this was done, and the old component instances delete, it all leapt into life.

I am not sure why I had the problems, I was trying to remember what I did exactly between the working and failing releases. All I can think is that I may have changed the password parameter to encrypted (I had forgotten to do this at first). Now I should have tried this sooner as I have posted on this error message before. All I can assume is that changing this parameter setting corrupted my component.

I should have read my own blog sooner

Moving our BlogEngine.NET server to Azure

As part of our IT refresh we have decided to move this BlogEngine.NET server from a Hyper-V VM in our office to an Azure website.

BlogEngine.NET is now a gallery item for Azure website, so a few clicks and your should be up and running.


However, if you want to use SQL as opposed to XML as the datastore you need to do a bit more work. This process is well documented in the video ‘Set BlogEngine.NET to use SQL provider in Azure’, but we found we needed to perform some extra steps due to where our DB was coming from.

Database Fixes

The main issue was that our on premises installation of BlogEngine.NET used a SQL 2012 availability group. This amongst other things, adds some extra settings that stop the ‘Deploy Database to Azure’ feature in SQL Management Studio from working. To address these issues I did the following:

Took a SQL backup of the DB from our production server and restored it to a local SQL 2012 Standard edition. I then tried the  Deploy to Azure


But got the errors I was expecting


There were three types

Error SQL71564: Element User: [BLACKMARBLE\AUser] has an unsupported property AuthenticationType set and is not supported when used as part of a data package.
Error SQL71564: Element Column: [dbo].[be_Categories].[CategoryID] has an unsupported property IsRowGuidColumn set and is not supported when used as part of a data package.
Error SQL71564: Table Table: [dbo].[be_CustomFields] does not have a clustered index.  Clustered indexes are required for inserting data in this version of SQL Server.

The first fixed by simply deleting the listed users in SQL Management Studio or via the query


The second were addressed by removing the  ‘IsRowGuidColumn’  property in Management Studio


or via the query


Finally II had to replace the non-cluster index with a cluster one. I got the required definition form the setup folder of our BlogEngine.NET installation, and ran the command

DROP INDEX [idx_be_CustomType_ObjectId_BlogId_Key] ON [dbo].[be_CustomFields]

CREATE CLUSTERED INDEX [idx_be_CustomType_ObjectId_BlogId_Key] ON [dbo].[be_CustomFields]
    [CustomType] ASC,
    [ObjectId] ASC,
    [BlogId] ASC,
    [Key] ASC

Once all this was done in Management Studio I could Deploy DB to Azure, so after a minute or two had a BlogEngine.NET DB on Azure

Azure SQL Login

The new DB did not have user accounts associated with it. So I had to create one

On the SQL server’s on Master  DB I ran

CREATE LOGIN usrBlog WITH password='a_password';

And then on the new DB I ran

EXEC sp_addrolemember N'db_owner', usrBlog

Azure Website

At this point we could have created a new Azure website using the BlogEngine.NET template in the gallery. However, I chose to create an empty site as our version of BlogEngine.NET (3.x) is newer than the version in the Azure gallery (2.9).

Due to the history of our blog server we have a non-default structure, the BlogEngine.NET code is not in the root. We retain some folders with redirection to allow old URLs to still work. So via an FTP client we create the following structure, copying up the content from our on premises server

  • \site\wwwroot  - the root site, we have a redirect here to the blogs folder
  • \site\wwwroot\bm-bloggers – again a redirect to the blogs folder, dating back to our first shared blog
  • \site\wwwroot\blogs – our actual server, this needs to be a virtual application

    Next I set the virtual application on the Configure section for the new website, right at the bottom, of the page


    At this point I was back in line with the video, so need to link our web site to the DB. This is done using the link button on the Azure  web site’s management page. I entered the new credentials for the new SQL DB and the DB and web site were linked. I could then get the connection string for the DB and enter it into the web.config.

  • Unlike  in the video the only edit I need to make was to the connection string, as all the other edits had already been made for the on premises SQL

    Once the revised web.config was uploaded the site started up, and you should be seeing it now

    BizTalk – Generating schemas from classes with TargetNamespace

    BizTalk provides a us a way of generating schemas from c# classes by using the xsd.exe tool which comes with the BizTalk SDK. The tool also allows us to generate c# classes from a schema and as an option we can specify the runtime namespace for the generated types. What would be nice is if we could specify the target namespace for the schemas when we generate them from our classes. As a BizTalk developer this can cause major headaches as you need to remember to add this manually every time you need to regenerate your schemas. After much investigate it turns out there is a way to get the target namespace into our schemas.

    So for example we have our C#’ class which may look something like this:

    using System.Xml.Serialization;
    namespace ServiceBusDemo.Model
         public class TodoItem
             public int ID { get; set; }
             public string Title { get; set; }
             public string Description { get; set; }
             public bool IsDone { get; set; }
         } }

    We run it though the xsd.exe tool and it generates us a schemas which looks like this:

      <?xml version="1.0" encoding="utf-16" ?>
    - <xs:schema xmlns:b="" elementFormDefault="qualified" xmlns:xs="">
      <xs:element name="TodoItem" nillable="true" type="TodoItem" />
    - <xs:complexType name="TodoItem">
    - <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="ID" type="xs:int" />
      <xs:element minOccurs="0" maxOccurs="1" name="Title" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" name="Description" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="IsDone" type="xs:boolean" />

    So normally at this point I would go in and manually add the targetnamespace, I probably misspell it, deploy my BizTalk solution and spend half a day wondering why my message are not being routed correctly.

    The solution to this is to simply add a reference to the System.Xml.Serialization namespace (Notice how on the msdn help page for the xsd.exe tool it states that the tool uses the System.Xml.Serialization.XmlSerializer) and add the XmlType and XmlRoot (for root elements) Attributes

    to your c# classes.

    using System.Xml.Serialization;
    namespace ServiceBusDemo.Model
         [XmlType(TypeName = "TodoItem", Namespace = "")]
    XmlRoot(ElementName = "TodoItem", Namespace = "")]
         public class TodoItem
             public int ID { get; set; }
             public string Title { get; set; }
             public string Description { get; set; }
             public bool IsDone { get; set; }
         } }

    Once we have defined the namespace we want to use, rerun the xsd.exe tool and this time all the work is done for us Smile

    <?xml version="1.0" encoding="utf-16" ?>
    - <xs:schema xmlns:b="" xmlns:tns="" elementFormDefault="qualified" targetNamespace="" xmlns:xs="">
      <xs:element name="TodoItem" nillable="true" type="tns:TodoItem" />
    - <xs:complexType name="TodoItem">
    - <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="ID" type="xs:int" />
      <xs:element minOccurs="0" maxOccurs="1" name="Title" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" name="Description" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="IsDone" type="xs:boolean" />

    Publishing more than one Azure Cloud Service as part of a TFS build

    Using the process in my previous post you can get a TFS build to create the .CSCFG and .CSPKG files needed to publish a Cloud Service. However, you hit a problem if your solution contains more that one Cloud Service project; as opposed to a single cloud service project with multiple roles, which is not a problem.

    The method outlined in the previous post drops the two files into a Packages folder under the drops location. The .CSPKG files are fine, as they have unique names. However there is only one ServiceConfiguration.cscfg, whichever one was created last.

    Looking in the cloud service projects I could find no way to rename the ServiceConfiguration file. It looks like it is like a app.config or web.config file i.e. it’s name is hard coded.

    The only solution I could find was to add a custom target that is set to run after the publish target. This was added to the end of each .CCPROJ files using a text editor just before the closing </project>

     <Target Name="CustomPostPublishActions" AfterTargets="Publish">
        <Exec Command="IF '$(BuildingInsideVisualStudio)'=='true' exit 0
        echo Post-PUBLISH event: Active configuration is: $(ConfigurationName) renaming the .cscfg file to avoid name clashes
        echo Renaming the .CSCFG file to match the project name $(ProjectName).cscfg
        ren $(OutDir)Packages\ServiceConfiguration.*.cscfg $(ProjectName).cscfg
        " />
        <PostBuildEvent>echo NOTE: This project has a post publish event</PostBuildEvent>


    Using this I now get unique name for the .CSCFG files as well as for .CSPKG files in my drops location. All ready for Release Management to pickup


    • I echo out a message in the post build event too just as a reminder that I have added a custom target that cannot be seen in Visual Studio, so is hard to discover
    • I use an if test to make sure the commands are only run on the TFS build box, not on a local build. The main reason for this is the path names are different for local builds as opposed to TFS build. If you do want a rename on a local build you need to change the $(OutDir)Packages path to $(OutDir)app.publish. However, it seemed more sensible to leave the default behaviour occur when running locally

    Getting the correct path and name for a project to pass as an MSBuild argument in TFS Build

    I have been sorting out some builds for use with Release Management that include Azure Cloud Solutions. To get the correct packages built by TFS I have followed the process in my past blog post. The problem was I kept getting the build error

    The target "Azure Packages\BlackMarble.Win8AppBuilder.AzureApi" does not exist in the project.

    The issue was I could not get the solution folder/project name right for the MSBUILD target parameter. Was it the spaces in the folder? I just did not know.

    The solution was to check the .PROJ file that was actually being run by MSBUILD. As you may know a .SLN file is not in MSBUILD format so you can’t just open it in notepad and look (unlike a .CSPROJ or .VBPROJ files), it is created by MSBUILD on the fly. To see this generated code, at a developer’s command prompt, run the following commands

    cd c:\mysolutionroot
    Set MSBuildEmitSolution=1

    When the MSBUILD command is run, whether the build works or not, there should be mysolution.sln.metaproj  file created. If you look in this file you will see the actual targets MSBUILD thinks it is dealing with.

    In my case I could see

    <Target Name="Azure Packages\BlackMarble_Win8AppBuilder_AzureApi:Publish">

    So the first issue was my . were replaced by _

    I changed my MSBUILD target argument to that shown in the file, but still had a problem. However, once I changed by space in the solution folder to %20 all was OK. So my final MSBUILD argument was



    Deploying a Windows service with Release Management

     recently needed to deploy a Windows service as part of a Release Management pipeline. In the past, our internal systems I have only need to deploy DB (via SSDT Dacpacs) and Websites (via MSDeploy), so a new experience.

    WIX Contents

    The first step to to create an MSI installer for the service. This was done using WIX, with all the fun that usually entails. The key part was a component to do the actual registration and starting of the service

    <Component Id ="ModuleHostInstall" Guid="{3DF13451-6A04-4B62-AFCB-731A572C12C9}" Win64="yes">
       <CreateFolder />
       <Util:User Id="ModuleHostServiceUser" CreateUser="no" Name="[SERVICEUSER]" Password="[PASSWORD]" LogonAsService="yes" />
       <File Id="CandyModuleHostService" Name ="DataFeed.ModuleHost.exe" Source="$(var.ModuleHost.TargetDir)\ModuleHost.exe" KeyPath="yes" Vital="yes"/>
       <ServiceInstall Id="CandyModuleHostService" Name ="ModuleHost" DisplayName="Candy Module Host" Start="auto" ErrorControl="normal" Type="ownProcess"  Account="[SERVICEUSER]" Password="[PASSWORD]" Description="Manages the deployment of Candy modules" />
       <ServiceControl Id="CandyModuleHostServiceControl" Name="ModuleHost" Start="install" Stop="both" Wait="yes" Remove="uninstall"/>

    So nothing that special here, but worth remembering if you miss out the ServiceControl block the service will not automatically start or be uninstalled with the MSI’s uninstall

    You can see that we pass in the service account to be used to run the service as a property. This is an important technique for using WIX with Release Management, you will want to be able to pass in anything you may want to change as installation time as a parameter. This means we ended up with a good few properties such as

      <Property Id="DBSERVER" Value=".\sqlexpress" />
      <Property Id="DBNAME" Value ="=CandyDB" />
      <Property Id="SERVICEUSER" Value="Domain\serviceuser" />
      <Property Id="PASSWORD" Value="Password1" />

    These tended to equate to app.config settings. In all cases I tried to set sensible default values so in most cases I could avoid passing in an override value.

    These property values were then used to re-write the app.config file after the copying of the files from the MSI onto the target server. This was done using the XMLFile tools and some XPath e.g.

    <Util:XmlFile Id="CacheDatabaseName" 
    ElementPath="/configuration/applicationSettings/DataFeed.Properties.Settings/setting[\[]@name='CacheDatabaseName'[\]]/value" Value="[CACHEDATABASENAME]" Sequence="1" />

    Command Line Testing

    Once the MSI was built it could be tested from the command line using the form

    msiexec /i Installer.msi /Lv msi.log SERVICEUSER="domain\svc_acc" PASSWORD="Password1" DBSERVER="dbserver" DBSERVER="myDB" …..

    I soon spotted a problem. As I was equating properties with app.config settings I was passing in connections strings and URLs, so the command line got long very quickly. It was really unwieldy to handle

    A check of the log file I was creating, msi.log, showed the command line seemed to be truncated. This seemed to occur around 1000 characters. I am not sure if this was an artefact of the logging or the command line, but either way a good reason to try to shorten the property list.

    I  therefore decided that I would not pass in whole connection strings, but just the properties that might change, especially effective for connection strings to things such as Entity Framework. This meant I did some string building in WIX during the transformation of the app.config file e.g.

    <Util:XmlFile Id='CandyManagementEntities1'
       File='[#ModuleHost.exe.config]' Value='metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|res://*/MyEntities.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=[DBSERVER];initial catalog=[DBNAME];integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;' />

    This technique had another couple of advantages

    • It meant I did not need to worry over spaces in strings, I could therefore lose the “ in the command line – Turns out this is really important later.
    • As I was passing in just a ‘secret value’ as opposed to a whole URL I could use the encryption features of Release Management to hide certain values

    It is at this point I was delayed for a long time. You have to be really careful when installing Windows services via an MSI that your service can actually start. If it cannot then you will get errors saying "… could not be installed. Verify that you have sufficient privileges to install system services". This is probably not really a rights issue, just that some configuration setting is wrong so the service has failed to start. In my case it was down to an incorrect connection string, stray commas and quotes, and a missing DLL that should have been in the installer. You often end up working fairly blind at this point as Windows services don’t give too much information when they fail to load. Persistence, SysInternals Tools and comparing to the settings/files on a working development PC are the best options

    Release Management Component

    Once I had working command line I could create a component in Release Management. On the Configure Apps > Components page I already had a MDI Deployer, but this did not expose any properties. I therefore copied this component to create a MSI deployer specific to my new service installer and started to edit it.

    All the edits were on the deployment tab, adding the extra properties that could be configured.


    Note: Now it might be possible to do something with the pre/post deployment configuration variables as we do with MSDeploy, allowing the MSI to run then editing the app.config later. However, given that MSI service installers tends to fail they cannot start the new service I think passing in the correct properties into MSIEXEC is a better option. Also means it is consistent for anyone using the MSI via the command line.

    On the Deployment tab I changed the Arguments to

    -File ./msiexec.ps1 -MsiFileName "__Installer__"  -MsiCustomArgs ‘SERVICEUSER=”__SERVICEUSER__”  PASSWORD=”__PASSWORD__” DBSERVER=”__DBSERVER__”  DBNAME=”__DBNAME__” …. ’

    I had initially assumed I needed the quotes around property values. Turns out I didn’t, and due to the way Release Management runs the component they made matters much, much worse. MSIEXEC kept failing instantly. if I ran the command line by hand on the target machine it was actually showing the Help dialog, so I knew the command line was invalid.

    Turns out the issue is Release Management calls PowerShell.EXE to run the script passing in the Arguments. This in turn calls a PowerShell Script which does some argument processing before running a process to run MSIEXEC.EXE with some parameters. You can see there are loads of places where the escaping and quotes around parameters could get confused.

    After much fiddling, swapping ‘ for “ I realised I could just forget most of the quotes. I had already edited my WIX package to build complex strings, so the actual values were simple with no spaces. Hence my command line became

    -File ./msiexec.ps1 -MsiFileName "__Installer__"  -MsiCustomArgs “SERVICEUSER=__SERVICEUSER__  PASSWORD=__PASSWORD__ DBSERVER=__DBSERVER__  DBNAME=__DBNAME__ …. “

    Once this was set my release pipeline worked resulting in a system with DBs, web services and window service all up and running.

    As is often the case it took a while to get this first MSI running, but I am sure the next one will be much easier.