visual studio, gruntlauncher, vssdk

When you create a Visual Studio extension to maximise its usefulness you try to make it work in all the most common Visual Studio versions which usually means VS 2012, 2013 and 2015.

This is not a big problem if you extension doesn’t target specific capabilities introduced only in the latest versions as every Visual Studio versions install the preceding versions libraries.

Sometimes, when you upgrade your extensions to target the new visual studio versions, you receive a complaint from someone that your extensions doesn’t work anymore. Further this seems to happen only if you have only an old VS version (usually only 2012) installed so you’re left to ponder what happened.

Searching on the internet for the specific message you find the likely cause, using newer versions of visual studio updated your project references to target the new dll versions which can’t be found in a system that only has vs 2012 installed.

A better search finds many results here, here and here suggesting some options :

  • creating two separate extensions to target VS2012 and VS2013
  • load dynamically the required library
  • manually edit you csproj to remove the new reference and pay attention to the fact that VS will always try to update them

Solution 1 is a no-go as I’m lazy and for a simple extension like Gruntlauncher I don’t want to mantain two separate version. Option 2 is doable but a little complex while solution 3 is the easiest but feels a lot like battling with Visual studio.

Luckily I found another options in the form of the VSSDK nuget pakages. These packages when installed allow you to always reference the correct version of the library without having to mantain separate version or resort tu ugly hacks.

tfs, grunt, gulp

In the past to execute grunt as part of a TFS build I’ve created a nuget package that modifies the msbuild file Grunt.MSBuild .

Having updated TFS to the 2013 version I’ve found there’s an easier way to do it by leveraging it’s ability to execute a Powershell script during the build. This can be done easily:

  • install grunt/gulp globally on every build agent. Pay attention to the fact that it must be installed as the user that runs the build agent and the grunt/gulp location must be included in the PATH variable (else you won’t be able to invoke grunt/gulp).
  • Add a powershell script inside your solution with the following lines

      Push-Location "$PSScriptRoot\..\Source\Web"  
      Write-Host "npm package restore"
      & "npm" install
      if ($LastExitCode -ne 0) {
        Write-Error "Npm package restore failed";
        exit 1;
      }
    
      Write-Host "Grunt requirejs"
      & "grunt" requirejs
      if ($LastExitCode -ne 0) {
        Write-Error "Grunt requirejs failed";
        exit 1;
      }
      Pop-Location
    
  • Modify your build definition to include the script by going in the process Tab -> Build section -> Advanced -> PreBuild script path
  • Run your newly configured build and enjoy.

The script it’s really simple but sometimes must be adapted to your configuration and can be easily extended. The first line moves the current working directory to the directory containing you package.json file and then executes an npm install to restore all the needed node packages. After that it exeutes grunt requirejs and finalyy restores the original working directory.

This step can be easily replaced by running gulp or extended by compiling your sass etcetera… .

grunt, gulp , gruntlauncher, edge

I use a lot grunt and gulp when working so, to improve my workflow with Visual Studio, I created the GruntLauncher extension which can parse a gulpfile or gruntfile and extract the contained tasks allowing you to execute them from inside VS.

To be able to do this I didn’t have many options so I used an hack: executing the file in a javascript engine and reading the option object to identify the tasks.

While this works it has many unhandled corner cases:

  • all the grunt utility functions must be present and defined
  • all the gulp utility functions must be present and defined
  • all the common node functions should be present and defined ( this is almost impossible to do as they are too many)

While this was an hack it worked quite well with just an handful of unhandled cases but everytime someone had a problem I got back to thinking to a better and more robust solution.

Then an idea dawned on me: Why should I mock all these functions and not simply ask to grunt and gulp for the defined config options? While this seems easy to do you have to remember that I cannot simply invoke the command line and look at the results as I need the whole options object for postprocessing and also because it’s not a perfect solution.

WIth some experiments I came to the following node.js code for gulp:

var gulp = require('gulp');
require('./gulpfile');
console.log(Object.keys(gulp.tasks).join(' '));

and a similar snippet for grunt (in this case I also look for subtasks)

var param = grunt.config.data;
var names = [];
for(var prop in param){
	if(param.hasOwnProperty(prop)){
		names.push(prop);
		if(param[prop] === Object(param[prop])){
		    var arr=[];
			for(var innerProp in param[prop]){
				if(param[prop].hasOwnProperty(innerProp)){
					if(innerProp!=='options'){
						arr.push(prop+":"+innerProp);
					}
				}
			}
			if(arr.length > 1){
				for (var i=0;i< arr.length;i++){
					names.push(arr[i]);
				}
			}
		}
	}
}

With these I can let gulp and grunt do the work, trusting the files to be well formed and the necessary plugins installed, then simply invoke this code from .NET thanks to Edge.js.

GruntLauncher is gonna get a serious refactoring..

css, scss, modern, animations

As I was working on a project I had to create a personal area page when a user could set some options to tweak the behaviour of the program.

As it always happens some of these options were of the type enable/disable behaviour which can be modelled with a simple checkbox.

While the checkbox works I felt the need for a more stylish solution and decided to try to replicate in CSS the Windows 8 checkbox.

First thing I searched the internet looking for a ready solution and found something close to what I wanted in Metro UI, which has a checkbox with the correct style but with a major defect: when clicked the checkbox switches state immediately ruining the overall effecct.

Solving this problem was quite easy and it took only the addition of a css animation on the slider movement and the slider color change.

The result and also the modified CSS code cand be seen here:

See the Pen bszrE by Paolo Nicodemo (@paonic) on CodePen.

Two things in this example are interesting to note:

  • an additional span is required to style everything correctly as some browsers don’t support the :after pseudoselector on an input field (Firefox if I remember correctly)
  • the animated transition is set not only on the span position but also on the original span so even the background color is animated thus giving a much more natural effect

angular, directive, javascript

Last week I was working on a SPA made with Angular and I was incurring in a classic problem: the double click.

You know the situation: a button is clicked, a call is made to the server to create a new order and after the call finishes the form closes. In my case if you were fast enough you could click a couple of times on the button before the call finished, resulting in multiple calls and multiple orders.

To solve this problem once and for all I decided to try my hand at creating a custom directive. Looking in Angular the source code I searched for the ng-click directive and modified it to create ng-single-click.

This directive can be used by simply substituting ng-click with ng-single-click. If the invoked expression returns something similar to a Promise (meaning it has a finally function) it will automatically ignore all the clicks on the element between the start of the promise and its fulfillment or rejection.

PS: After some tests I noticed that stopping clicks without giving the user a hint that work is currently being done is not a good user experience so I created a second version of this directive that adapts ladda-button to show a working animation in the clicked button.