Friday 17 February 2017

Service Fabric PowerShell

start-service fabrichostsvc - starts the fabric cluster

Tuesday 14 February 2017

Changing the resolution of an Ubuntu guest in a Hyper-V host

Ensure the system is updated
sudo apt-get update

1. Delete the monitor configuration
sudo rm ~/.config/monitors.xml

2. Set the startup resolution
sudo vi /etc/default/grub
Set GRUB_CMDLINE_LINUX_DEFAULT="quiet splash video=hyperv_fb:1680x1050" (or whatever)

3. Update grub
sudo update-grub

How to uninstall Virtual Box Guest Client


VirtualBox to Hyper-V conversions

I was reluctantly forced to use Oracle Virtual Box as my company wouldn't allow me to install Windows 10 and use Hyper-V. But after a period of time - I loved it!

But eventually the day came when I upgraded to Windows 10 and then I wanted to use the Hyper-V containers so I could use containers with Service Fabric and Docker. It was a reluctant upgrade.

Some of my VMs were VMDKs (VMWare format).
When I tried to use the  ConvertTo-MvmcVirtualHardDisk PowerShell converter I encountered the error:

ConvertTo-MvmcVirtualHardDisk : The entry 9805522d-8707-43d0-a4b2-60f05833e201 is not a supported disk database entry for the descriptor.

Fortunately this post helped me and I used the dsfok and dsfik tools to export and import the modified descriptors.
Although they describe a different field, I eneded up commenting out other fields (shown below).


After that the ConvertTo-MvmcVirtualHardDisk worked.

Friday 10 February 2017

Docker / Windows Container Service on Windows 2016 - Storage Location

Images are stored under C:\ProgramData\Docker\image\WindowsFilter\imagedb\content\sha256
where the GUID matches that returned by the PowerShell command

docker images

NServiceBus sends data on Azure Service Bus encoded as Base64 / UTF8

I was writing an Azure Function to receive Azure Service Bus messages sent by an NServiceBus endpoint.

Naively, I thought I could simply decode the body as a string. I was wrong.

I would get the error:
Exception while executing function: Functions.OnOrderCreated. mscorlib: Exception has been thrown by the target of an invocation. System.Runtime.Serialization: Expecting element 'string' from namespace ''.. Encountered 'Element' with name 'base64Binary', namespace ''. .

After an investigation, I discovered that NServiceBus sets the property NServiceBus.Transport.Encoding to the value wcf/byte-array.

The message body looks like this:

<base64Binary xmlns="">77u/eyJBbGxvY2F0aW9uSWQiOiIx...... Simplified ....</base64Binary>

and if you base 64 decode the element content and encode using UTF8 you get the following output in the debugger window:

{"AllocationId":"18475fa4-c696-4992-a559-f48b7cab4cab","CreatedDate":"2017-02-10T11:18:03.7281344+00:00","CurrencyCode":"GBP","SizeSchema":"UK","Products":..... Simplified .... }

However if you then try and use JSONConvert to deseriaize it into a typed object, it errors with:

"Unexpected character encountered while parsing value: . Path '', line 0, position 0."

This is because there are a hidden three bytes which are not shown in the debugger window but which are shown if you look at the byte array. The three bytes are the Byte Order Mark: EF BB BF (239 187 191). These need to be stripped out.

The code below - used in Linqpad - demonstrates a way of getting at the inner content.

void Main()
 Uri uri = ServiceBusEnvironment.CreateServiceUri("sb", "mytest", string.Empty);
 string topicName = "bundle-1";
 string subscriptionName = "Linqpad";
 string name = "RootManageSharedAccessKey";
 string key = "";
 string connectionString = "Endpoint=sb://;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=";
 TokenProvider tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(name, key);
 NamespaceManager namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
 SubscriptionClient Client = SubscriptionClient.CreateFromConnectionString(connectionString, topicName, subscriptionName);
 OnMessageOptions options = new OnMessageOptions();
 options.AutoComplete = false;
 options.AutoRenewTimeout = TimeSpan.FromMinutes(1);
 Client.OnMessage((message) =>
   // Console.WriteLine("Transport encoding: " + message.Properties["NServiceBus.Transport.Encoding"]);
   var xml = message.GetBody();   
   var body = Convert.FromBase64String(xml.InnerText);
   var contentWithBom = Encoding.UTF8.GetString(body);
   // content.Dump();
   // Remove the BOM from the string
   var contentWithoutBom = Encoding.UTF8.GetString(body, 3, body.Length - 3);
    var orderCreated = JsonConvert.DeserializeObject(contentWithoutBom);
  catch (Exception error)
   // Indicates a problem, unlock message in subscription.
 }, options);

 string input = "";
 Console.WriteLine("Press x to stop");
 while (!input.ToLower().StartsWith("x"))
  input = Console.ReadLine();

Wednesday 8 February 2017

Adding external references to Azure Functions: CS0009 "PE image doesn't contain managed metadata".

I had an Azure Function that referenced an external assembly:

#r "Orders.Contracts.dll"
#r "Newtonsoft.Json"

using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Orders.Contracts;

public static void Run(string myQueueItem, TraceWriter log)
    log.Info($"C# ServiceBus queue trigger function processed message: {myQueueItem}");

    var orderCreated = JsonConvert.DeserializeObject(myQueueItem);

    log.Info($"orderCreated Reference: {orderCreated.OrderReference}");


External assemblies have to be added to the bin folder on the function's folder; e.g. D:\home\site\wwwroot\OnOrderCreated\bin.

Firstly I connected to the home site using FileZilla and created the bin and uploaded the DLL.
I got the error

CS0009 "PE image doesn't contain managed metadata".

I then tried a similar technique, but this time went to Function App Setting > Open Dev Console and created the bin folder and uploaded the DLL using FileZilla. That failed too.

In the end I found the best way was to use the Kudu console. I created the bin folder and drag-and-dropped the file from explorer into the Kudu file browser window. This then fixed the error.

Navigate to /site/wwwroot/
add folder bin
upload files to bin

Friday 3 February 2017

WebJob learnings

You can attach a debugger to a Web Job.

The Attach Debugger option appears greyed out in the Visual Studio Cloud Explorer window. The best solution is to attach the debugger directly in Visual Studio.

You need to set the qualifier to the Web Job address (note that this is the URL with .scm in the hostname and not the underlying Web App URL).
The username and password can be found by downloading the Publish Profile for the Web App in the portal.

The process is displayed in the Available Processes window. The first time I uploaded a Web Job manually to a Web App created in the portal, it didn't appear. When I built and deployed the Web App and the Web Job from Visual Studio, this worked better.

WebJob must have AzureWebJobsDashboard setting configured in the portal

I deployed a Web Job and when it ran I got the error that the configuration was not properly set.

I added the connection string to the Web App web.config and redeployed, however it still didn't work. It appears that although the Web Job will have access to this connection string, the dashboard requires it to be added via the portal.