VSTS and Git Integration for Deploying to Azure – Part 1

At work we use Visual Studio Team Services (VSTS) with git and in this post I’ll walk you through our development process for writing code and deploying it to a demo site on Azure.

I have become a big fan of VSTS, it has some cracking functionality built-in which saves you a lot of time and effort.

I will cover the following:-

Using Visual Studio 2017 with the git integration tools

So I open up Visual Studio 2017 and I first of all need to update my local copy of the master branch and pull down the latest version.

To do this I select Sync as shown above and then I choose fetch to fetch the latest commits and pull to pull them all down as below.


Ok, so now I have the latest code from the master branch as seen below.

Now I want to run the master branch and see if everything is good and check whats changed with the commits I pulled down but before I can do this I need to apply some local settings.

The reason for this is we have a number of Azure Services being used like event hubs etc and I have a local settings json file with my settings which I never check in. To apply these local settings I saved them into a stash and I will show you how I apply my stashes next.

So I click Stashes within Team Explorer and then I see the following.

 

And now I right-click on local settings and select apply stash, and this will apply my local settings to the project allowing me to run my own event hub instead of the one on our demo site as an example.

In order to get the Git Stash Extension you can download it from Extensions and Updates from the Tools menu within Visual Studio.

 

In Part 2 https://gregorsuttie.com/2018/08/24/vsts-and-git-integration-for-deploying-to-azure-part-2/ – I’ll show you how to use VSTS build pipelines to build and test your code and then deploy it to Azure.

Squirrel – replace ClickOnce the easy way

Last week I was taking a look at Squirrel which states

Squirrel: It’s like ClickOnce but Works™

The goal of me looking at Squirrel was to find a decent replacement to ClickOnce, I read a tweet from @paulcbetts mentioning his work and how he had created Squirrel as a replacement to using ClickOnce.

Having spent some time implementing this and coming across one or two issues which I overcame, the good news is ClickOnce is hopefully no longer needed.

Squirrel works and does exactly what we require, our windows forms application’s can have a ‘check for updates’ option, which updates to the latest release, close the old application down after its updated, re-open from the original desktop or start menu shortcut and your done.

Steps to get Squirrel working

  1. Sourcecode is on GitHub.
  2. Create a simple Windows Forms Application
  3. Add the nuget package called squirrel.windows nugetinstalllike so:-
  4. Add the following to the program.cs like so (line 19 is the only one I added) :-
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    using Squirrel;
    
    namespace WindowsFormsApplication1
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                SquirrelAwareApp.HandleEvents(onAppUpdate: Form1.OnAppUpdate, 
                onAppUninstall: Form1.OnAppUninstall, 
                onInitialInstall: Form1.OnInitialInstall); 
                
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    }
    
  5. Add some content like a simple button or a menu with the choice to check for updates
  6. in the code behind we implement squirrel like so:-
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    using System.Configuration;
    using Squirrel;
    using System.Reflection;
    using System.IO;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private const ShortcutLocation DefaultLocations = ShortcutLocation.StartMenu 
           | ShortcutLocation.Desktop; 
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
            {
                // Check for Squirrel Updates
                var t = UpdateApp();
            }
    
            public async Task UpdateApp()
            {
                var updatePath = ConfigurationManager.AppSettings["UpdatePathFolder"];
                var packageId = ConfigurationManager.AppSettings["PackageID"];
    
                using (var mgr = new UpdateManager(updatePath, packageId, FrameworkVersion.Net45))
                {
                    var updates = await mgr.CheckForUpdate();
                    if (updates.ReleasesToApply.Any())
                    {
                        var lastVersion = updates.ReleasesToApply.OrderBy(x => x.Version).Last();
                        await mgr.DownloadReleases(new[] { lastVersion });
                        await mgr.ApplyReleases(updates);
                        await mgr.UpdateApp();
    
                        MessageBox.Show("The application has been updated - please close and restart.");
                    }
                    else
                    {
                        MessageBox.Show("No Updates are available at this time.");
                    }
                }
            }
    
            public static void OnAppUpdate(Version version)
            {
                // Could use this to do stuff here too.
            }
    
            public static void OnInitialInstall(Version version)
            {
                var exePath = Assembly.GetEntryAssembly().Location;
                string appName = Path.GetFileName(exePath);
    
                var updatePath = ConfigurationManager.AppSettings["UpdatePathFolder"];
                var packageId = ConfigurationManager.AppSettings["PackageID"];
    
                using (var mgr = new UpdateManager(updatePath, packageId, FrameworkVersion.Net45))
                {
    
                    // Create Desktop and Start Menu shortcuts
                    mgr.CreateShortcutsForExecutable(appName, DefaultLocations, false);
                }
            }
    
            public static void OnAppUninstall(Version version)
            {
                var exePath = Assembly.GetEntryAssembly().Location;
                string appName = Path.GetFileName(exePath);
    
                var updatePath = ConfigurationManager.AppSettings["UpdatePathFolder"];
                var packageId = ConfigurationManager.AppSettings["PackageID"];
    
                using (var mgr = new UpdateManager(updatePath, packageId, FrameworkVersion.Net45))
                {
                    // Remove Desktop and Start Menu shortcuts
                    mgr.RemoveShortcutsForExecutable(appName, DefaultLocations);
                }
            }
        }
    }
    
  7. We now need to create a .nuspec file which we will use to package up our application, Squirrel needs to have every file within the lib\net45 folder.

    To create a .nuspec file I simply copied nuget.exe into the solution and then went to a command prompt and typed:- nuget spec, this creates a .nuspec file which we can then hand edit inside Visual Studio and looks like this:-

    <?xml version="1.0"?>
    <package >
      <metadata>
        <id>WindowsFormsAppliation1</id>
        <version>1.0.0.0</version>
        <authors>Gregor Suttie</authors>
        <title>WindowsFormsAppliation1 Squirrel Tester</title>
        <description>Testing out Squirrel</description>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <releaseNotes>None</releaseNotes>
        <copyright>Copyright 2015</copyright>
      </metadata>
      <files>
        <file src="bin\Debug\*.*" target="lib\net45\"></file>
      </files>
    </package>
    
  8. Next we need to pack the .nuspec file to generate the nuget package, so run the following:-
    Nuget pack WindowsFormsApplication1.nuspec
  9. From the package manager console inside Visual Studio we now need to run the following command:-

    squirrel –releasify C:\Squirrel\WindowsFormsApplication1\WindowsFormsApplication1\WindowsFormsApplication1.1.0.0.0.nupkg

  10. In the folder above we should now have a folder called Releases, containing a setup.exe which we use to install the application.
  11. Run setup.exe and your app will install with shortcuts on the desktop and the start menu if you use the code above which has defined these as shortcut options.
  12. If you then run check for updates, the code will go off and check the folder you specify in the app.config like so:-
    <add key="UpdatePathFolder" value="c:\updatesForMyApp\"/>
    
  13. In order to update our app we also need the following appsetting which is the id of the Nuget package we created earlier, be careful not to have the id with a space or a dot (.) within the Nuget package Id.:-
    <add key="PackageID" value="WindowsFormsApplication1"/>
    
  14. Also add this one line to the assmblyinfo.cs:-
    [assembly: AssemblyMetadata("SquirrelAwareVersion", "1")]
    
  15. Once you install the application, go back and make a change to the code, save it, update the .nuspec file version number from 1.0.0 to 1.0.1 and then redo steps 7 and 8 (with the path to the new WindowsFormsApplication1.1.0.0.1.nupkg file)
  16. Almost done, copy the content of the releases folder to our location where we store the updates (our app.config setting for UpdatePathFolder which was set to c:\updatesForMyApp\)
  17. Run the app and choose the menu option ‘Check for Updates’ and you’ll get the latest version.
  18. Also note of you add a Debugger.Launch() statement in the code you can debug the code and step through line by line.

To find out more about further options available and much more about Squirrel click here.

AspConf – My Review

Last week we had AspConf – “aspConf is a virtual conference focused on one thing: showcasing the ASP.NET stack as the platform for great web applications.

Over 2 days they had 5 virtual rooms used to present lots of fascinating stuff on .Net, including talks about all manner of things in the Asp.Net world.

The sessions on both days covered topics such as, Async in .Net 4.5, Glimpse, TDD, Azure and Cloud Computing and lots lots more, you can read more about the sessions here.

Although it had some technical difficulties, due to its popularity I may add, the conference is an awesome way to learn for free – and free is always good. It’s a superb way to learn about content you havent had time to look at it, or new technologies you havent heard of. Hopefully next year they might try to use something different from livemeeting.

If you missed any of the session then fret not, most of them if not all of them were recorded and put up on Channel 9 here

I only managed to see sessions from day 2 so I am off to go watch more content on Channel 9 – a great resource for free learning.