Saturday, January 20, 2018

General workflow for publishing an Android app to the Google Play store when developing with VSTS


  1. Create a Git repository (not TFVC) in VSTS, possibly with a new Team Project, up to you.
  2. Create your app in Android Studio and add it to the Git repository.
  3. Create your Key Store (or import an existing one) with Android Studio.
    • In order to be able to sign your APK and deploy it (with any tool, but in this case VSTS), you'll need the following 3 pieces of information:
      • The Key Store password
      • The Key alias
      • The Key password
  4. Ensure that you've imported the "Manifest Versioning Build Tasks" extension to your VSTS account from the VSTS Marketplace.
  5. Configure and execute an automated build for your application using the default steps provided by VSTS when creating a new build by applying the Android build template.
    1. Add to the default build templae a "Manifest Versioning Build Tasks" step to automatically generate your application version from the build.
  6. In your Google account, do the following:
    1. Ensure that you've gone to the Google Play Console page and created a Developer Page.
      • Once you've created the Service Account below, you'll need to come back here to the Play Console and grant access with "RELEASE MANAGEMENT" permissions, ensuring that you also have the "Release manager" role selected.
      • ENSURE THAT YOU'VE COMPLETED ALL THE WARNINGS IN THE NAVIGATION PANE IN THE GOOGLE PLAY CONSOLE, OTHERWISE YOU WON'T BE ABLE TO ROLL-OUT ANY OF YOUR RELEASES.
    2. Ensure that you've gone to the Google API Console and created a Service Account for publishing your app to the Google Play store.
      • NOTE: You'll need to export your key in JSON format so that the email and key fields within the JSON object can be used to configure your Google Play endpoint in VSTS
  7. Ensure that you've imported the Microsoft "Google Play" extension into your VSTS account from the Marketplace.
  8. Configure your automated Release in VSTS. Execute the following steps:
    1. Add an "Android Signing" step to your release to sign one of the *unsigned* APKs from your build.
    2. Add a "Google Play - Release" step to your release. You'll need the keystore information mentioned above, as well as the keystore *.jks file to upload to VSTS in the "Google Play - Release" step.
  9. Now that your release is configured, you'll have to to a manual build on your developer (just once) to product a signed APK with the keystore, and then manually upload the signed APK file to the Google Play Console to an Alpha release in order to associate your applicationId (in the ApplicationManifest.xml app manifest file) to your product in the Play Store.

Friday, January 12, 2018

Bootstrapping a VSTS Linux build agent for Docker containers

1. Create an Ubuntu 17.04 VM in Azure
2. Install dotnetcore using the instructions here.
3. Install the Docker apt-get package using the instructions here.
4. Download and run the VSTS agent Docker image and run it as a Docker container itself using the instructions here, e.g. sudo docker run -e VSTS_ACCOUNT=myvstsaccountname -e VSTS_TOKEN=abcdtokenherefromportal -e VSTS_POOL="Docker Build Agents" -e VSTS_AGENT="myagentname" -it -v /var/run/docker.sock:/var/run/docker.sock microsoft/vsts-agent

Tuesday, January 09, 2018

Using Git with a corporate firewall that uses certificate interception

Like many open source tools (originally or completely) based on Linux, git has issues with self-signed certificates, especially if you work in a corporate environment where your company may have network message inspection hardware for security. To get git to work in such an environment, you'll need the public root Certificate Authority certificate for your company, exported to a base 64 .cer file. Once you have that, run the following command to install it into git's private certificate store:

git config --global http.sslCAInfo "<path/to/your/certfile.cer or .pem>"

Wednesday, January 03, 2018

Using NodeJS with a corporate firewall that uses certificate interception

See this post on Stack Overflow. The gist of it:

1. Export your company's corporate Root CA certificate to a Base64 encoded .cer file
2. Run this command to instruct npm to use the certificate file in its communications:

npm config set cafile = "<path to your certificate file>"

Tuesday, December 12, 2017

Installing Windows 10 IoT Core on a Raspberry Pi 3

You’ll need the following ingredients:

1. A desktop or laptop computer with Windows 10 installed
2. A Raspberry Pi 3.
3. A Micro-SD card for use as the primary storage on the RasPi3
4. A Micro-USB cable for connecting the RasPi3 to a power sources
5. A mouse and keyboard
6. A monitor with HDMI support, or an HDMI to [whatever] adapter for your monitor
7. A wired network connection for the RasPi3.

To get up and running with Windows 10 IoT Core on a Raspberry Pi 3, you’ll need to follow these high-level steps:

1. Ensure you’ve got Windows 10 on your developer machine. If you don’t, go get a machine with Windows 10 and don’t come back here until you do.
2. Download the Windows 10 Iot Core Dashboard . You’ll need it to configure your Micro SD card for the RasPi 3.
3. Insert the Micro-SD card into your computer and use the IoT Core Dashboard to configure the MicroSD card with Windows 10 IoT Core.
4. Once successful, insert the MicroSD card into the unpowered RasPi3 and plug it in to power it up. 5. You should also have your monitor, mouse and keyboard hooked up by this point.
6. Configure the RasPi3 to connect to your network, and ensure that your Desktop computer with the dashboard and the RasPi3 are on the same network so that the Dashboard can detect your RasPi3.
7. Use the Windows 10 IoT Core Dashboard on your desktop PC to connect the RasPi3 to an IoT Hub in Azure.

Sunday, November 12, 2017

The quick and dirty for using System.Windows.Interactivity and the MVVM pattern for custom dialogs in your WPF application

So I recently decided to finally try my hand at using proper MVVM patterns with my custom dialogs in the application on which I'm currently working (started back in 2010 before a lot of MVVM frameworks existed). I followed Microsoft's Interactivity Getting-started guide here. The quick summary of steps to take (as a reminder) are below. That said, read the article tip-to-tail so that you understand these steps, and then use this page as a reminder.


  1. For your dialog (e.g. MyDialog), you'll need to create the following items:
    • MyDialogViewModel, which implements Prism.Interactivity.InteractionRequest.IInteractionRequestAware
    • MyDialogConfirmation, which extends from Prism.Interactivity.InteractionRequest.Confirmation
  2. In your dialog, ensure that it extends from System.Windows.Control.UserControl, NOT System.Windows.Window (because your interactivity request handler in XAML needs a control for its Content, not a Window)
  3. In the constructor of your Dialog user control, set your data context to a new instance of your MyDialogViewModel (to ensure that it's present in the DataContext when the Interactivity framework invokes your dialog's window and can inject it with your MyDialogConfirmation instance when you raise the notification for your InteractivityRequest to which you're binding
  4. Ensure you've created your interactivity handler in the XAML of the view that's calling your dialog, e.g.:
 <i:Interaction.Triggers>
  <prism:InteractionRequestTrigger SourceObject="{Binding Path=MyDialogInteractivityRequestProperty, Mode=OneWay}">
   <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
    <prism:PopupWindowAction.WindowContent>
     <Dialogs:MyDialog />
    </prism:PopupWindowAction.WindowContent>
   </prism:PopupWindowAction>
  </prism:InteractionRequestTrigger>
 </i:Interaction.Triggers>

Wednesday, October 18, 2017

A quirk when using Ninject with Self-Hosted WCF services

I recently discovered a problem when using WCF in a self-hosted setup that I had never encountered before:

I was using the following binding syntax in my module:

this.Bind<IMyService, MyServiceImpl>();

As it turned out, this was causing a strange "Object reference not set to instance of an object". Changing the syntax to :

this.Bind<IMyService>().To<MyServiceImpl>().InTransientScope();

... solved the problem.

Using Ninject in a Self-Hosted environment, e.g. a Windows Service

Windows Services are a great way to host WCF, typically in scenarios where on-premise services are a requirement. As Dependency Injection becomes a standard practice in large scale systems, it can be hard to choose the right DI container. One of my personal favourites in Ninject because of its (typical) ease of configuration. Some benchmarks will show that Ninject isn't the fastest container out there in terms of constructing objects, but in practical use I've never once found that to be a problem.

The following example shows a function that can be used in a Windows Service for setting up Ninject to create ServiceHost instances in a self-hosting scenario:

private static NinjectServiceHost CreateServiceHost(IKernel standardKernel, Type serviceType)
{
 if (standardKernel == null)
 {
  throw new ArgumentNullException("standardKernel");
 }
 
 if (serviceType == null)
 {
  throw new ArgumentNullException("serviceType");
 }
 
 NinjectServiceHost ninjectServiceHost = new NinjectServiceHost(
  serviceBehavior: new NinjectServiceBehavior(
   instanceProviderFactory: type => new NinjectInstanceProvider(type, standardKernel),
   requestScopeCleanUp: new WcfRequestScopeCleanup(true)
   ),
  serviceType: serviceType
 );
 
 return ninjectServiceHost;
}

This function will be good enough to boot strap your services in your Windows ServiceBase
implementation in the vast majority of cases. You need only pass in your pre-configured 
IKernel instance and the Type of the WCF Service implementation.

Friday, October 13, 2017

Resolving PowerShell cmdlets with conflicting names

I've recently run into the issue of needing to use multiple modules that happen to contain cmdlets that have the same name in each. According to this article, you can use module name qualified cmdlet calls to resolve naming conflicts.

Tuesday, September 26, 2017

Loading the Solver add-in for Excel so that you can perform graphical analysis of charts


For starters, see here. For the quick start version, see here:
  1. File => Options => Add-ins
  2. Check "Active Application Add-ins" first to see if it's already loaded. If "Solver Add-in" is not in there, search under "Inactive Application Add-ins"
  3. Near the bottom of the window, under the "Manage" drop-down, select "Excel Add-ins" and hit the Go button.
  4. Ensure the "Solver Add-in" button is checked off, then click the "Ok" button and save all the way back to your workbook.

Monday, September 25, 2017

How to include multiple Earned Value charts on the same graph


  1. Ensure that you have your Earned Value data series all in the same workbook
  2. Ensure that the date series' for your Earned Value series are actually formatted as dates
  3. Start by rendering the first Earned Value series as a SCATTER PLOT with straight lines
  4. Edit the chart data to add subsequent Earned Value series until they're all on the same chart

TODO: Update this post to include screen shots.

How to quickly graph a comparison of projects with PDEx in Excel 2016


  1. Select your projects in Windows Explorer, right click => Open 
  2. Once all of your projects are loaded into an instance of Microsoft Project with PDEx installed, go to the "Project Design" tab and click on "Compare": 
  3. In the window that opens up to compare your Projects, go to the Summary tab:
  4. Click somewhere in the table of values and press Ctrl+A to select all of the cells: 
  5. Press Ctrl+C to copy the contents of the table to the clipboard.
  6. Open a new Excel workbook, and on a blank worksheet, go to cell A1: 
  7. Press Ctrl+V to paste the table of values from MS Project into Excel: 
  8. Select a SINGLE column of data across projects that you'd like to graph and click on the quick action icon in the bottom right, e.g. Total Cost:
  9. In the Quick Action dialog that appears, select the "Charts" tab: 
  10. Click on the "Scatter" chart type to generate a Scatter plot of the data points. This will generate the series on the Y-axis, with default serial numbers as the X-axis:
  11. Right click on the chart and select "Edit Data" to edit the data series:
  12. In the "Select Data Source" dialog that appears, select the created data series and click on the "Edit" button to edit it: 
  13. In the "Edit Series" dialog that appears, select the cell that's to be used for the series name, and the range of cells that are to be used as the X-axis for the data series. Then click Ok to save the changes, and OK again to close the Series editor: 
  14. Once back in the main Excel window, with the Chart still in Edit mode, go to the top right of the data area and hover over the corner until you have an "Expand" mouse cursor: 
  15. Click on the corner anchor and drag to the right to include extra data series extracted from the neighbouring columns: 
  16. Now that you've got all of the series you want to include on the graph (Cost in our case), you'll need to pare down the X-axis to have the series' fill out the chart. Right-click on the X-axis and select Format Axis: 
  17. In the "Format Axis" pane that appears on the right side of the Excel window, set appropriate X-axis bounds: 
  18. In order to match the graphs we see in the Project Design manual which include data labels that have the names of the corresponding project variants, start by right-clicking on one of the data series and then clicking on "Add Data Labels": 
  19. This will add default data labels with the Y-values of the data points to the series. However, we want to use the names of the corresponding projects, so we have more work to do. Right-click on one of the data labels and click on "Format Data Labels ...": 
  20. In the "Format Data Labels" pane that appears on the right side of the Excel window, select "Value from Cells". This will cause the "Data Label Range" dialog to appear: 
  21. Click on the textbox in the "Data Label Range", then select the cells under the "Project" column, EXCLUDING THE "PROJECT" HEADER. Then click OK: 
  22. You'll now have your chart for your project comparison data, with (at least one) series set up to look just like the Project Design manual: 
Happy charting!

Saturday, September 16, 2017

The Tech Lead's New Project Checklist, propagated

A while ago a virtual colleague recommended this article on a forum:

https://insimpleterms.blog/2017/08/07/the-tech-leads-new-project-checklist/

It's a checklist for all the items a Technical Lead  should enumerate on a New Project. It's a good read if you're in (or could potentially be in) the position of leading a team in a technical project.

Wednesday, September 06, 2017

Useful PowerPoint Shit, Part 2 - Cloning objects quickly

I don't like using the mouse, but if I have to I will. Here's some tips for quickly cloning items in PowerPoint:


  1. Duplicating a shape - Ctrl+C, Ctrl+V OR Ctrl+D (while not in text edit mode) OR Ctrl+Mouse drag
  2. Duplicating a slide - Ctrl+Shift+D

Useful PowerPoint Shit, Part 1 - Copying and Pasting Shape Attributes

I love using hotkeys to execute my tasks because they reduce the number of times my hand has to leave the keyboard and go for the mouse, and consequently accelerate the task at hand. I've recently had cause to start using PowerPoint a lot more as my role at the company where I work has shifted and my job description has changed somewhat.

That said, I've discovered this useful gem for copying attributes between shapes so that I don't have to use the mouse and navigate menus to clone items or otherwise search for paste options:

Copy the attributes of a shape
  1. Select the shape with the attributes that you want to copy. ...
  2. Press CTRL+SHIFT+C to copy the shape attributes.
  3. Press the TAB key or SHIFT+TAB to select the shape or object that you want to copy the attributes to.
  4. Press CTRL+SHIFT+V.


Thursday, August 31, 2017

Fixing github access behind a corporate firewall with self-signed certificates

If you're doing development with bower packages in Visual Studio projects behind a corporate firewall, you may have run into issues with self-signed certificates. The quickest and easiest way to get around this (though definitely not safest or most recommended) is to simply globally ignore self-signed certificates.

On your Developer Command Prompt (assuming you've got 'git' in your PATH):

git config --global http.sslverify false

Fixing Bower behind a corporate firewall

Our company uses software to intercept and inspect encrypted packets (like many other corporate entities). As a result, there are self-signed certificates added to the packets. This creates a problem with many package managers like npm and bower.

If you're looking to get started quickly with bower in your .NET application in Visual Studio, simply put a .bowerrc file with the following contents in the root of your project (next to, say, your web.config):

{ "strict-ssl": false }

Sunday, August 13, 2017

Azure Automation does not support the Process{} block

There's an undocumented bug in Azure Automation: it does NOT support the Process { } block, i.e. the block that you would use when creating scripts / modules where you need to support piping in your commands.

I discovered this after much trial and error trying to run a runbook and having it silently and mysteriously fail with no output whatsoever, no matter what verbosity and progress settings I enabled.

Re-adding a Hybrid Runbook Worker to an Automation Account runbook worker group

If you receive the error: Add-HybridRunbookWorker : Machine is already registered to different account

Simply delete the key under: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\HybridRunbookWorker and try the command again.

Thanks go to Wayne Hoggett for pointing this out, this point reprints his.

Sunday, July 30, 2017

Unit testing Service Fabric Reliable Service and Actors with Mocks and Moqs

Install-Package Moq
Install-Package ServiceFabric.Mocks

Some key bits of code you'll need:

this.mockRepository = new MockRepository(MockBehavior.Strict);

var statefulServiceContext = MockStatefulServiceContextFactory.Create(
codePackageActivationContext: this.mockRepository.Create<ICodePackageActivationContext>().Object,
serviceTypeName: String.Concat(typeof(MyActorService).Name, "Type"),
serviceName: new Uri("fabric:/MockApplicationType/MyActorServiceType"),
partitionId: Guid.NewGuid(),
replicaId: 1
);

this.mockServiceDependencyThing = this.mockRepository.Create<IServiceDependencyThing>();

MockActorService<MyActorService> actorServiceForActor = MockActorServiceFactory.CreateActorServiceForActor<MyActorService>((actorService, actorId) => new MyActorService(actorService, actorId, this.mockServiceDependencyThing.Object));

this.sut = new MyActorService(actorServiceForActor, new ActorId(Guid.NewGuid()), this.mockServiceDependencyThing.Object);