Friday, February 20, 2015

Get Code Coverage from VS without writing automated tests

Create a batch file somewhere in your system as such:
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Team Tools\Performance Tools\vsinstr.exe" -coverage "%1"
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Team Tools\Performance Tools\VSPerfCmd.exe" /start:coverage /output:run.coverage
start "%1" /wait "%1"
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Team Tools\Performance Tools\VSPerfCmd.exe" /shutdown
notepad "run.coverage"
echo "%1"
echo "%2"

Create an External Tool Entry in your Visual Studio Tools Menu.
  • Title: RunCovered

  • Command: c:\projects\config\batches\RunCovered.bat
  • Arguments
    $(TargetName)$(TargetExt) $(BinDir)
  • Initial Directory:

replace the command with wherever your new shiny batch file lives.

Then in trigger that External Tool on the Tools Menu.

It will launch your app, and you can then click around or do whatever is needed to activate parts of your application, and the results will be saved into the same directory as your executable file as run.coverage. Open this file in your already open Visual Studio instance, or drag and drop the file from explorer into VS.

There you have your App's coverage metrics for that run.

Thursday, November 13, 2014

Binding redirects at runtime

Hopfully the C# audience can read this F#, but this is how you would do it =)
printfn "starting up"
open System
open System.Reflection

let RedirectAssembly shortName (targetVersion : Version) publicKeyToken = 
    let rec onResolveEvent = new ResolveEventHandler( fun sender evArgs ->
        let requestedAssembly = 
        if requestedAssembly.Name <> shortName 
            printfn "redirect firing for %s" requestedAssembly.Name; Unchecked.defaultof<Assembly>
                "Redirecting assembly load of %s ,\tloaded by %s" 
                (if evArgs.RequestingAssembly = null then 
            requestedAssembly.Version <- targetVersion
            requestedAssembly.SetPublicKeyToken (AssemblyName(sprintf "x, PublicKeyToken=%s" publicKeyToken).GetPublicKeyToken())
            requestedAssembly.CultureInfo <- System.Globalization.CultureInfo.InvariantCulture
            Assembly.Load (requestedAssembly)
// sample usage
RedirectAssembly "FSharp.Core" (Version("")) "b03f5f7f11d50a3a"

Thursday, October 9, 2014

Using a Git layer on top of TFS

Not having git bugs me. Working with any other source control system takes away some of my power.

With a git layer over whatever other source control system is required for the team:

  • I can check-in or revert individual lines of code in a file. 
  • I can create a branch for local modifications that should never be checked into the team source control.
  • I can create mini-commits that don't have to be logged as individual commits in the team source (for teams that prefer one large change-set)
    • I can create my own personal historical record of change save-points and notes/comments
  • I can select which lines of a file should go into a check-in without shelving the entire change.

How to:

Create a junction or hardlink to the folder that contains your code. This junction must not be in the tree that your tfs workspace mapping sees. If it is, Visual Studio will then, forcefully and persistently, use git as your source control and refuse to talk to TFS about your changes.

So I have all my code under c:\development\foo

  1.  I change working directory to c:\projects\bar and mklink /h /j foobar c:\development\foo
  2. git init
  3. Always point visual studio at the legacy folder c:\development\foo.
  4. Always point your git tool(s) at c:\projects\bar
  5. profit!

Monday, June 30, 2014

Why am I so enthusiastic about F#?

I'm suddenly really passionate about F#. This is new as of ~3 weeks ago.

Thursday, April 17, 2014

T4 ApiController Generator

This T4 assumes your DbContext is called ApplicationDbContext in a file called ApplicationDbContext.cs and does not account for whatever custom namespaces need to be imported for this file for your use. It is set up for DI, but lacks consumption of an IRepository pattern or anything similar. It also expects to be in a directory below the EnvDteHelper.ttinclude.
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data.Entity.Design" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Data.Entity.Design.PluralizationServices" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<# DTE Dte;#>
<#@ include file="../EnvDteHelper.ttinclude"#>
  var suggestedNs=System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint");
  var projects = RecurseSolutionProjects(Dte);
  var q= from p in projects
      from pi in p.ProjectItems.Cast<ProjectItem>()
      where pi.FileCodeModel!=null
      select new{p,pi,CodeElements=pi.FileCodeModel.CodeElements.Cast<CodeElement>()};
  var context= q.Where(x=>x.pi.Name=="ApplicationDbContext.cs").First();
  var typesToMap = Descendants(context.CodeElements,ce=>ce.Children.Cast<CodeElement>()).OfType<CodeProperty>();
  var project=GetProjectContainingT4File(Dte,false);
  var pluralizationService = PluralizationService.CreateService(new CultureInfo("en-US"));
using System.Linq;
using System.Web.Http.OData;

using Microsoft.AspNet.Identity.EntityFramework;

namespace <#=suggestedNs#>
<#  foreach(var tm in typesToMap){
  var singular=pluralizationService.Singularize(tm.Name);
  var plural=pluralizationService.Pluralize(tm.Name);

    public class <#=tm.Name#>Controller : ODataController
        readonly ApplicationIdentityContext _db;

        public <#=tm.Name#>Controller(ApplicationIdentityContext db)
            _db = db;

        /// GET api/<#=singular#>
        public IQueryable<<#=singular#>> Get()
            return _db.<#=plural#>;

        // GET api/<#=singular#>/5
        public <#=singular#> Get(int id)
            return _db.<#=plural#>.FirstOrDefault(x=>x.<#=singular#>Id==id);