autofac, net comments edit

As part of DNX RC1, the Microsoft.Framework.* packages are getting renamed to Microsoft.Extensions.*.

The Autofac.Framework.DependencyInjection package was named to follow along with the pattern established by those libraries: Microsoft.Framework.DependencyInjection -> Autofac.Framework.DependencyInjection.

With the RC1 rename of the Microsoft packages, we'll be updating the name of the Autofac package to maintain consistency: Autofac.Extensions.DependencyInjection. This will happen for Autofac as part of beta 8.

We'll be doing the rename as part of the beta 8 drop since beta 8 appears to have been pushed out by a week and we'd like to get a jump on things. For beta 8 we'll still refer to the old Microsoft dependency names to maintain compatibility but you'll have a new Autofac dependency. Then when RC1 hits, you won't have to change the Autofac dependency because it'll already be in line.

You can track the rename on Autofac issue #685.

powershell, vs, net comments edit

I love PowerShell, but I do a lot with the Visual Studio developer prompt and that's still good old cmd.

Luckily, you can make your PowerShell prompt also a Visual Studio prompt.

First, go get the PowerShell Community Extensions. If you're a PowerShell user you should probably have these already. You can either get them from the CodePlex site directly or install via Chocolatey.

Now, in your PowerShell profile (stored at %UserProfile%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1) add the following:

Import-Module Pscx

# Add Visual Studio 2015 settings to PowerShell
Import-VisualStudioVars 140 x86

# If you'd rather use VS 2013, comment out the
# above line and use this one instead:
# Import-VisualStudioVars 2013 x86

Next time you open a PowerShell prompt, it'll automatically load up the Visual Studio variables to also make it a Visual Studio prompt.

Take this to the next level by getting a "PowerShell Prompt Here" context menu extension and you're set!

net, build, tfs comments edit

I'm working with some builds in Visual Studio Online which, right now, is basically Team Foundation Server 2015. As part of that, I wanted to do some custom work in my build script but only if the build was running in TFS.

The build runs using the Visual Studio Build build step. I couldn't find any documentation for what additional / special environment variables where available, so I ran a small build script like this...

<Exec Command="set" />

...and got the environment variables. For reference, here's what you get when you run the Visual Studio Build task on an agent with Visual Studio 2015:

AGENT_NAME=Hosted Agent
BUILD_DEFINITIONNAME=Continuous Integration
BUILD_QUEUEDBY=[DefaultCollection]\Project Collection Service Accounts
CommonProgramFiles=C:\Program Files (x86)\Common Files
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
CommonProgramW6432=C:\Program Files\Common Files
GTK_BASEPATH=C:\Program Files (x86)\GtkSharp\2.12\
Path=C:\LR\MMS\Services\Mms\TaskAgentProvisioner\Tools\agent\worker\Modules\Microsoft.TeamFoundation.DistributedTask.Task.Internal\NativeBinaries\amd64;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\DTS\Binn\;C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\;C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0\;C:\Program Files\Microsoft SQL Server\120\Tools\Binn\;C:\Users\VssAdministrator\.dnx\bin;C:\Program Files\Microsoft DNX\Dnvm\;C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\;C:\Program Files (x86)\Microsoft Emulator Manager\1.0\;C:\Program Files (x86)\GtkSharp\2.12\bin;C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.4\;C:\Program Files (x86)\Git\bin;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PrivateAssemblies\;C:\Program Files (x86)\Microsoft SQL Server\110\DTS\Binn\;C:\Program Files (x86)\Microsoft SQL Server\120\Tools\Binn\ManagementStudio\;C:\Program Files (x86)\Microsoft SQL Server\120\Tools\Binn\;C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\PrivateAssemblies\;C:\Program Files (x86)\Microsoft SQL Server\120\DTS\Binn\;C:\Program Files\Microsoft\Web Platform Installer\;C:\NPM\Modules;C:\Program Files\nodejs\;C:\NPM\Modules;C:\cordova;C:\java\ant\apache-ant-1.9.4\bin;
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 45 Stepping 7, GenuineIntel
ProgramFiles=C:\Program Files (x86)
ProgramFiles(x86)=C:\Program Files (x86)
ProgramW6432=C:\Program Files
PSModulePath=C:\Users\buildguest\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules\;C:\Program Files\SharePoint Online Management Shell\;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\;C:\Program Files (x86)\Microsoft SQL Server\120\Tools\PowerShell\Modules\;C:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\ServiceManagement;C:\LR\MMS\Services\Mms\TaskAgentProvisioner\Tools\agent\worker\Modules
VS100COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Tools\
VS110COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\
VS120COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\
VS140COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\
VSSDK110Install=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\
VSSDK120Install=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VSSDK\
VSSDK140Install=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VSSDK\
WIX=C:\Program Files (x86)\WiX Toolset v3.7\
XNAGSShared=C:\Program Files (x86)\Common Files\Microsoft Shared\XNA\

Note that BUILDCONFIGURATION and BUILDPLATFORM are parameters to the Visual Studio Build task. You'll see that text right in the TFS build system dashboard.

The BUILD_BUILDNUMBER value is the one I'm the most interested in - that's what I can key off to set the assembly version. TF_BUILD seems to be what you use to determin if the build is running in TFS.

autofac, net comments edit

In the continuing journey toward the Autofac 4.0.0 release, some integration/extras packages have been released:

  • Autofac.Wcf 4.0.0: Doesn't require Autofac 4.0 but is tested to be compatible with it. .NET 4.0 framework support is removed; minimum is now .NET 4.5. No interface changes were made - the major semver increment is for the .NET compatibility break. AllowPartiallyTrustedCallers and other pre-4.5 security markings are also removed.
  • Autofac.Mef 4.0.0: Doesn't require Autofac 4.0 but is tested to be compatible with it. .NET 4.0 framework support is removed; minimum is now .NET 4.5. No interface changes were made - the major semver increment is for the .NET compatibility break. AllowPartiallyTrustedCallers and other pre-4.5 security markings are also removed.
  • Autofac.Extras.AttributeMetadata 4.0.0: This is a rename from Autofac.Extras.Attributed to Autofac.Extras.AttributeMetadata to express what it actually attributes. Doesn't require Autofac 4.0 but is tested to be compatible with it. Requires Autofac.Mef 4.0 due to the security attribute changes and minimum .NET 4.5 requirement.
  • Autofac.Multitenant.Wcf 4.0.0-beta7-223: The WCF component compatible with Autofac.Multitenant 4.0 beta. This will stay in beta until Autofac.Multitenant can also be fully released. This is a rename from Autofac.Extras.Multitenant.Wcf to match the rename of Autofac.Extras.Multitenant to Autofac.Multitenant. Requires Autofac.Wcf 4.0 due to the security attribute changes and minimum .NET 4.5 requirement.

There's a lot going on to try and keep up with DNX compatibility (where possible) and checking/testing existing integration packages to ensure they still work with Autofac 4. For the most part, it seems just updating things to use .NET 4.5 instead of .NET 4.0 allows us to retain forward-compatibility, though in some cases the code access security changes require changes.

We're working hard on it. Watch our Twitter feed for announcements!

autofac, net comments edit

I just pushed Autofac.Multitenant 4.0.0-beta8-216 to NuGet.

This update includes some breaking changes from the previous Autofac.Extras.Multitenant package:

  • Multitenant support has been promoted to first-class. The package is now Autofac.Multitenant and not Autofac.Extras.Multitenant. (Note the "Extras" part is gone. We always talked about how, at some point, an "Extras" package might become a core feature, figured it was time to finally actually do that.)
  • This package requires Autofac 4.0.0-beta8-* and up because...
  • The multitenant support has been updated to support the same set of portable platforms that core Autofac supports (dnx451, dotnet, net45, netcore45).
  • This builds on top of DNX beta 8.

If you're using DNX and want to try out multitenancy, give this a shot. If you find any issues, please let us know at the Autofac.Multitenant repo!

personal, costumes comments edit

I normally don't sew too much outside of Halloween, when it becomes more an excuse to set aside time to make cool stuff than anything else. However, I saw this "Exploding TARDIS" fabric at Jo-Ann the other day and had to make something out of it.

Since my daughter Phoenix is a Whovian like myself, I figured I'd make her a little dress. I went with Butterick "See & Sew" pattern B5443 because it was a whopping $3 and it was a fairly simple thing. I also got some shiny blue lining to go in it.

The exploding TARDIS fabric, lining, and pattern

The most time consuming part was, as usual, pinning and cutting all the pieces.

Cutting the main pieces

The back closes in a zipper, which is usually a painful experience but actually went smoothly this time. Here I'm pinning it in...

Pinning the zipper

...and here it's finished.

The finished zipper

I did a bit of a modification and let the blue lining hang slightly below the body of the dress for a peek of that shiny blue. I also finished the waist with a ribbon that has gold sun, moon, and stars printed on it.

The 'exploding TARDIS' dress

And here is the proud four-year-old Whovian in her new exploding TARDIS dress.

Phoenix in her new dress

All told it took about a day and a half from start to finish. I really started around 10 or 11 on Saturday, ran it through until around 10 Saturday night, and finished up in a couple of hours on Sunday morning. Not too bad.

This was the first thing I've made since I got Jenn a Brother 1034D serger for Christmas, and let me tell you - the serger makes all the difference. The seams come out very professional looking and the garment has a much more "store bought" quality to it.

I bought enough of the fabric to make myself a shirt using Vogue pattern 8800. I've used that pattern before and it comes out well, if a bit snug, so this next go-round with it I'll make one size larger for some breathing room.

synology, security comments edit

In November of last year I set up a PPTP VPN on my Synology NAS so I could do more secure browsing on public wifi. Since then, I've updated my setup to use OpenVPN and made the connection a lot easier.

I based the steps to get my connection working on this forum post but I didn't do quite the extra work with the certificates.

Assuming you've got the VPN package installed and ready to go on your Synology NAS (which I walk through in the previous article), the next steps to get OpenVPN going are:

  • Open the VPN Server application in the Diskstation Manager.
  • Enable the OpenVPN protocol by checking the box. Leave everything else as default.
  • At the bottom of the OpenVPN panel, click "Export Configuration." This will give you the profile you'll need for your devices to connect to the VPN.
  • In the Control Panel, go to the "Security" tab. On the "certificate" panel, click "Export Certificate." Save that somewhere and call it ca.crt. This is a little different than what I was expecting - I had hoped the certificates that come in the OpenVPN zip file (when you export that configuration) would just work, but it turns out I needed to get this particular certificate. YMMV on this.
  • Just like with the PPTP VPN, make sure the firewall has a rule to allow port 1194 (the OpenVPN port) through. You also need to create a port forwarding rule for port 1194 with your router. You can see how to do this in my other article.

You should have OpenVPN up and running. That part, at least for me, was the easiest part. The harder part was getting my Android phone connected to it and trying to automate that.

First things first, let's get connected.

Install the OpenVPN Connect app for Android. There are several OpenVPN apps out there; I use this one and the rest of my article will assume you do, too. The app is free, so there's no risk if you don't like it.

Open the zip file of exported OpenVPN configuration you got from the Synology and pull out the openvpn.ovpn file. Pop that open in a text editor and make sure that...

  • The remote line at the top points to your public DNS entry for your Synology, like or whatever you set up.
  • The ca line has ca.crt in it.

Here's what it should generally look like. I've left the comments in that are there by default.

dev tun

remote 1194

# The "float" tells OpenVPN to accept authenticated packets from any address,
# not only the address which was specified in the --remote option.
# This is useful when you are connecting to a peer which holds a dynamic address
# such as a dial-in user or DHCP client.
# (Please refer to the manual of OpenVPN for more information.)


# If redirect-gateway is enabled, the client will redirect it's
# default network gateway through the VPN.
# It means the VPN connection will firstly connect to the VPN Server
# and then to the internet.
# (Please refer to the manual of OpenVPN for more information.)


# dhcp-option DNS: To set primary domain name server address.
# Repeat this option to set secondary DNS server addresses.

#dhcp-option DNS DNS_IP_ADDRESS


# If you want to connect by Server's IPv6 address, you should use
# "proto udp6" in UDP mode or "proto tcp6-client" in TCP mode
proto udp

script-security 2

ca ca.crt


reneg-sec 0


Put the ca.crt certificate you exported and the openvpn.ovpn file on your Android device. Make sure it's somewhere you can find later.

Open the OpenVPN Connect app and select "Import Profile." Select the openvpn.ovpn file you pushed over. Magic should happen and you will see your VPN show up in the app.

Now's a good time to test the connection to your VPN. Enter your username and password into the OpenVPN Connect app, check the Save button to save your credentials, and click the "Connect" button. It should find your VPN and connect. When you connect you may see a little "warning" icon saying network communication could be monitored by a third-party - that's Android seeing your Synology's certificate. You should also see OpenVPN Connect telling you you're connected.

OpenVPN Connect showing the connection is active

It's important to save your credentials in OpenVPN Connect or the automation of connecting to the VPN later will fail.

If you're not able to connect, it could be a number of different things. Troubleshooting this is the biggest pain of the whole thing. Feel good if things worked the first time; I struggled figuring out all the certificates and such. Things to check:

  • Did you enter your username/password correctly using an account defined on the Synology?
  • Does the account you used have permissions to the VPN? (By default it should, but you may be trying to use a limited access account, so check that.)
  • Did the router port forwarding get set up?
  • Did the firewall rule get set up?
  • Is your dynamic DNS entry working?
  • Is the ca.crt in the same folder on your Android device as the openvpn.ovpn file?
  • If that ca.crt isn't working, did you try the one that came in the zip file with the OpenVPN configuration you exported? (The one in that zip didn't work for me, but it might work for you.)
  • Consider trying the instructions in this forum post to embed the certificate info right in the openvpn.ovpn file.

From here on out, I assume you can connect to your VPN.

Now we want to make it so you connect automatically to the VPN when you're on a wifi network that isn't your own. I even VPN in when I'm on a "secure" network like at a hotel where you need a password because, well, there are a lot of people on there with you and do you trust them all? I didn't think so.

Install the Tasker app for Android. This one will cost you $3 but it's $3 well spent. Tasker helps you automate things on your Android phone and you don't even need root access.

I found the instructions for setting up Tasker with OpenVPN Connect over on the OpenVPN forums via a reddit thread. I'll put them here for completeness, but total credit to the folks who originally figured this out.

The way Tasker works is this: You create "tasks" to run on your phone, like "show an alert" or "send an email to Mom." You then set up "contexts" so Tasker knows when to run your tasks. A "context" is like "when I'm at this location" or "when I receive an SMS text message" - it's a condition that Tasker can recognize to raise an event and say, "run a task now!" Finally, you can tie multiple "contexts" together with "tasks" in a profile - "when I'm at this location AND I receive an SMS text message THEN send an email to Mom."

We're going to set up a task to connect to the VPN when you're on a network not your own and then disconnect from the VPN when you leave the network.

You need to know the name of your OpenVPN Connect profile - the text that shows at the top of OpenVPN Connect when you're logging in. For this example, let's say it's [openvpn]

  1. Create a new task in Tasker. (You want to create the task first because it's easier than doing it in the middle of creating a profile.)
    1. Call the task Connect To Home VPN.
    2. Use System -> Send Intent as the action.
    3. Fill in the Send Intent fields like this (it is case-sensitive, so be exact; also, these are all just one line, so if you see line wraps, ignore that):
      • Action: android.intent.action.VIEW
      • Category: None
      • Mime Type:
      • Data:
      • Extra: net.openvpn.openvpn.AUTOSTART_PROFILE_NAME: [openvpn]
      • Extra:
      • Extra:
      • Package:net.openvpn.openvpn
      • Class: net.openvpn.openvpn.OpenVPNClient
      • Target: Activity
  2. Create a second new task in Tasker.
    1. Call the task Disconnect From Home VPN.
    2. Use System -> Send Intent as the action.
    3. Fill in the Send Intent fields like this (it is case-sensitive, so be exact; also, these are all just one line, so if you see line wraps, ignore that):
      • Action: android.intent.action.VIEW
      • Category: None
      • Mime Type:
      • Data:
      • Extra:
      • Extra:
      • Extra:
      • Package:net.openvpn.openvpn
      • Class: net.openvpn.openvpn.OpenVPNDisconnect
      • Target: Activity
  3. Create a new profile in Tasker and add a context.
    1. Use State -> Net -> Wifi Connected as the context.
    2. In the SSID field put the SSID of your home/trusted network. If you have more than one, separate with slashes like network1/network2.
    3. Check the Invert box. You want the context to run when you're not connected to these networks.
  4. When asked for a task to associate with the profile, select Connect To Home VPN.
  5. On the home screen of Tasker you should see the name of the profile you created and, just under that, a "context" showing something like Not Wifi Connected network1/network2.
  6. Long-press on the context and it'll pop up a menu allowing you to add another context.
    1. Use State -> Net -> Wifi Connected as the context.
    2. Leave all the other fields blank and do not check the Invert box.
  7. On the home screen of Tasker you should now see the profile has two contexts - one for Not Wifi Connected network1/network2 and one for Wifi Connected *,*,*. This profile will match when you're on a wifi network that isn't in your "whitelist" of trusted networks. Next to the contexts you should see a little green arrow pointing to Connect To Home VPN - this means when you're on a wifi network not in your "whitelist" the VPN connection will run.
  8. Long-press on the Connect To Home VPN task next to those contexts. You'll be allowed to add an "Exit Task." Do that.
  9. Select the Disconnect From Home VPN task you created as the exit task. Now when you disconnect from the untrusted wifi network, you'll also disconnect from the VPN.

You can test the Tasker tasks out by going to the "Tasks" page in Tasker and running each individually. Running the Connect To Home VPN task should quickly run OpenVPN Connect, log you in, and be done. Disconnect From Home VPN should log you out.

If you're unable to get the Connect To Home VPN task working, things to check:

  • Did you save your credentials in the OpenVPN Connect app?
  • Do you have a typo in any of the task fields?
  • Did you copy your OpenVPN Connnect profile name correctly?

You should now have an Android device that automatically connects to your Synology-hosted OpenVPN whenever you're on someone else's network.

The cool thing about OpenVPN that I didn't see with PPTP is that I don't have to set up a proxy with it. I got some comments on my previous article where some folks were lucky enough to not need to set up a proxy. I somehow needed it with PPTP but don't need it anymore with OpenVPN. Nice.

NOTE: I can't offer you individual support on this. Much as I'd like to be able to help everyone, I just don't have time. I ask questions and follow forum threads like everyone else. If you run into trouble, Synology has a great forum where you can ask questions so I'd suggest checking that out. The above worked for me. I really hope it works for you. But it's not fall-down easy and sometimes weird differences in network setup can make or break you.

autofac, net, testing comments edit

Autofac DNX support is under way and as part of that we're supporting both DNX and DNX Core platforms. As of DNX beta 6, you can sign DNX assemblies using your own strong name key.

To use your own key, you need to add it to the compilationOptions section of your project.json file:

  "compilationOptions": {
    "keyFile": "myApp.snk"

Make sure not to specify keyFile and strongName at the same time - you can only have one or the other.

The challenge we ran into was with testing: We wanted to run our tests under both DNX and DNX Core to verify the adjustments we made to handle everything in a cross-platform fashion. Basically, we wanted this:

dnvm use 1.0.0-beta6 -r CLR
dnx test/Autofac.Test test
dnvm use 1.0.0-beta6 -r CoreCLR
dnx test/Autofac.Test test

Unfortunately, that yields an error:

System.IO.FileLoadException : Could not load file or assembly 'Autofac, Version=, Culture=neutral, PublicKeyToken=null' or one of its dependencies. General Exception (Exception from HRESULT: 0x80131500)
---- Microsoft.Framework.Runtime.Roslyn.RoslynCompilationException : warning DNX1001: Strong name generation is not supported on CoreCLR. Skipping strongname generation.
error CS7027: Error signing output with public key from file '../../Build/SharedKey.snk' -- Assembly signing not supported.
Stack Trace:
     at Autofac.Test.ContainerBuilderTests.SimpleReg()
  ----- Inner Stack Trace -----
     at Microsoft.Framework.Runtime.Roslyn.RoslynProjectReference.Load(IAssemblyLoadContext loadContext)
     at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(AssemblyName assemblyName, IAssemblyLoadContext loadContext)
     at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(AssemblyName assemblyName)
     at assemblyName)
     at assemblyName)
     at Microsoft.Framework.Runtime.Loader.AssemblyLoaderCache.GetOrAdd(AssemblyName name, Func`2 factory)
     at Microsoft.Framework.Runtime.Loader.LoadContext.Load(AssemblyName assemblyName)
     at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyName(AssemblyName assemblyName)
     at System.Runtime.Loader.AssemblyLoadContext.Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName)

I ended up filing an issue about it to get some help figuring it out.

Under the covers, DNX rebuilds the assembly under test rather than using the already-built artifacts. This was entirely unclear to me since you don't actually see any rebuild process happen. If you turn DNX tracing on (set DNX_TRACE=1) then you actually will see that Roslyn is recompiling.

If you want to test the same build output under different runtimes, you need to publish your tests as though they are applications. Which is to say, you need to use the dnu publish command on your unit test projects, like this:

dnu publish test\Your.Test --configuration Release --no-source --out C:\temp\Your.Test

When you run dnu publish you'll get all of the build output copied to the specified output directory and you'll get some small scripts corresponding to the commands in the project.json. For a unit test project, this means you'll see test.cmd in the output folder. To execute the unit tests, you run test.cmd rather than dnx test\Your.Test test on your tests.

The Autofac tests now run (basically) like this:

dnvm use 1.0.0-beta6 -r CLR
dnu publish test\Autofac.Test --configuration Release --no-source --out .\artifacts\tests
dnvm use 1.0.0-beta6 -r CoreCLR

Publishing the unit tests bypasses the Roslyn recompile, letting you sign the assembly with your own key but testing under Core CLR.

I published an example project on GitHub showing this in action. In there you'll see two build scripts - one that breaks because it doesn't use dnu publish and one that works because it publishes the tests before executing.

autofac comments edit

Today we pushed the following packages with support for DNX beta 6:

This marks the first release of the Autofac.Configuration package for DNX and includes a lot of changes.

Previous Autofac.Configuration packages relied on web.config or app.config integration to support configuration. With DNX, the new configuration mechanism is through Microsoft.Framework.Configuration and external configuration that isn't part of web.config or app.config.

While this makes for a cleaner configuration story with a lot of great flexibility, it means if you want to switch to the new Autofac.Configuration, you have some migration to perform.

There is a lot of documentation with examples on the Autofac doc site showing how new configuration works.

A nice benefit is you can now use JSON to configure Autofac, which can make things a bit easier to read. A simple configuration file might look like this:

    "defaultAssembly": "Autofac.Example.Calculator",
    "components": [
            "type": "Autofac.Example.Calculator.Addition.Add, Autofac.Example.Calculator.Addition",
            "services": [
                    "type": "Autofac.Example.Calculator.Api.IOperation"
            "injectProperties": true
            "type": "Autofac.Example.Calculator.Division.Divide, Autofac.Example.Calculator.Division",
            "services": [
                    "type": "Autofac.Example.Calculator.Api.IOperation"
            "parameters": {
                "places": 4

If you want, you can still use XML, but it's not the same as the old XML - you have to make it compatible with Microsoft.Framework.Configuration. Here's the above JSON config converted to XML:

<?xml version="1.0" encoding="utf-8" ?>
<autofac defaultAssembly="Autofac.Example.Calculator">
    <components name="0">
        <type>Autofac.Example.Calculator.Addition.Add, Autofac.Example.Calculator.Addition</type>
        <services name="0" type="Autofac.Example.Calculator.Api.IOperation" />
    <components name="1">
        <type>Autofac.Example.Calculator.Division.Divide, Autofac.Example.Calculator.Division</type>
        <services name="0" type="Autofac.Example.Calculator.Api.IOperation" />

When you want to register configuration, you do that by building up your configuration model first and then registering that with Autofac:

// Add the configuration to the ConfigurationBuilder.
var config = new ConfigurationBuilder();

// Register the ConfigurationModule with Autofac.
var module = new ConfigurationModule(config.Build());
var builder = new ContainerBuilder();

Again, check out the documentation for some additional detail including some of the differences and new things we're supporting using this model.

Finally, big thanks to the Microsoft.Framework.Configuration team for working to get collection/array support into the configuration model.

javascript, home comments edit

I have, like, 1,000 of those little keyring cards for loyalty/rewards. You do, too. There are a ton of apps for your phone that manage them, and that's cool.

Loyalty card phone apps never work for me.

For some reason, I seem to go to all the stores where they've not updated the scanners to be able to read barcodes off a phone screen. I've tried different phones and different apps, all to no avail.

You know what always works? The card in my wallet. Which means I'm stuck carrying around these 1,000 stupid cards.

There are sites, some of them connected to the phone apps, that will let you buy a combined physical card. But I'm cheap and need to update just frequently enough that it's not worth paying the $5 each time. I used to use a free site called "JustOneClubCard" to create a combined loyalty card but that site has gone offline. I think it was purchased by one of the phone app manufacturers. ((Seriously.)


Enter: LoyaltyCard

I wrote my own app: LoyaltyCard. You can go there right now and make your own combined loyalty card.

You can use the app to enter up to eight bar codes and then download the combined card as a PDF to print out. Make as many as you like.

And if you want to save your card? Just bookmark the page with the codes filled in. Done. Come back and edit anytime you like.

Go make a loyalty card.

Behind the Scenes

I made the app not only for this but as a way to play with some Javascript libraries. The whole app runs in the client with the exception of one tiny server-side piece that loads the high-resolution barcodes for the PDF.

You can check out the source over on GitHub.

vs comments edit

I installed Visual Studio 2015 today. I had the RC installed and updated to the the RTM.

One of the minor-yet-annoying things I found about the RTM version showed up when I pinned it to my taskbar next to VS2013:

Confusing icons on the taskbar


Luckily it's an easy fix.

Windows 7 / Server 2008

First, unpin VS2015 from your taskbar. You'll put it back after you've fixed the icon.

Open up your Start menu and right-click on the "Visual Studio 2015" shortcut in there. On the context menu, choose "Properties." Click the "Change Icon" button.

Click the 'Change Icon' button

VS2015 actually comes with a few icons. They're not all awesome, but they're at least different than the VS2013 icon. I chose the one with the little arrow because it's, you know, upgraded from VS2013.

Pick a better icon

Click OK enough times to close all the property dialogs. You'll see the icon in the Start menu has changed. Now right-click that and pin it to the taskbar. Problem solved.

At least you can tell which is which now

Windows 8 / Server 2012

If you haven't pinned VS2015 to your taskbar yet, do that now so you can get a shortcut.

Open up the taskbar icons folder. This is at C:\Users\yourusername\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar.

Copy the "Visual Studio 2015" shortcut out of that folder and onto your desktop.

Unpin VS2015 from your taskbar. The shortcut in that TaskBar folder will disappear.

Right-click on the "Visual Studio 2015" shortcut you copied to your desktop. On the context menu, choose "Properties." Click the "Change Icon" button.

Click the 'Change Icon' button

VS2015 actually comes with a few icons. They're not all awesome, but they're at least different than the VS2013 icon. I chose the one with the little arrow because it's, you know, upgraded from VS2013.

Pick a better icon

Click OK enough times to close all the property dialogs. You'll see the icon on your desktop has changed.

Right-click on the icon on your desktop and pin that one to your taskbar. A new shortcut with the correct icon will be added to that TaskBar folder and will appear on the taskbar. You can now delete the one from your desktop.

At least you can tell which is which now

gaming, xbox comments edit

I tried playing a couple of Xbox 360 Kinect games with my four-year-old daughter, Phoenix. We had less than stellar results.

The first game was "Sesame Street TV." Basically it's interactive Sesame Street. We picked it up from the library to try it and I'm glad it was free.

Problem 1: She's very small compared to me. If the Kinect sees me, it somehow stops seeing her. And vice versa - if it sees her, it stops detecting me. There seemed to be a sort of very small "magic area" in the room where it'd find both of us.

Problem 2: The interaction for that game isn't constant. It's more like: they sing a song, then you have a small bit of interaction, then they tell a story, then there's a small bit of interaction. She'll watch or she'll interact, but she loses interest in interacting once you switch to watching.

Problem 3: Slight misrepresentation of the game on the box. The concept behind the game is like you going into the TV and being on Sesame Street. There is a picture on the box to illustrate the concept. Phoenix wants that to be the reality. It is really hard to explain that the box just shows an idea of what it's like, that you don't really transfer yourself into the television.

After a bit of Sesame Street, we tried "Kinect Adventures." I did this thinking that the constant interaction would keep her engaged.

We still ran into the problem where there was basically the small area where it recognized us both, but then it was compounded with a couple of new problems.

Problem 4: Many of the games aren't obvious to four-year-olds. In particular, the game where you have to walk from side to side and jump to control the raft - that was entirely unintuitive to Phoenix. She was far more concerned with whether or not the avatar on the raft actually looked like her, which then led to a half-hour diversion where we had to set up an avatar.

Problem 5: Auto jump-in/jump-out. The ability to jump in and out of the game quickly is great for folks that "get it" and when you have a properly sized room without the "magic area" where you're recognized. However, every time Phoenix accidentally stepped out of the "magic area," her avatar would disappear because it thought she was jumping out of the game, at which point I'd have to try to convince her to come back into the area - but not too close to me - so we could continue.

In the end, we decided it a better idea to just go watch some Looney Tunes cartoons we picked up at the library. Which, now that I think about it, is sort of the opposite of what Kinect is trying to get you to do - get off the couch and be active. Hmmm.

Over the years I've posted about my home media center developments. Back in 2008 I posted a summary with links to articles, then I did another roundup in 2014.

The problem with this sort of periodic summary is that it's hard to get an accurate picture of how things are working right now. I might forget to blog it, or I'll take some notes on something I found and forget to post it, or whatever.

I was keeping my media center and home networking notes in a personal wiki on PBworks but I figured it was time to make things a bit more official.

My media center and home network documentation is now live at

Diagram of my home network

This is the place I'll add notes or tips on how my media center setup works. I've got everything from the hardware I use to my process for getting video content into the system. I've got my plan and analysis for how I cut cable including cost breakdowns and options. It's all on this site.

My biggest problem in getting my media center going was that I didn't know what I didn't know. Information about all this stuff - hardware, software, how to get things done - is spread out all over the place. I never found a complete guide to help me on my way.

I hope this documentation can help you jump start your media center or improve the one you have. As things change in my system, I'll be keeping the documentation here up to date so it should always have the latest info.

home, media, music, movies comments edit

We finally did it: We cut the cable.

On Friday, we took all the cable boxes back to Comcast, cut off the cable TV and the phones, and we're down to internet service and mobile phones only.

I have to say, I know I'm only a few days into it but I haven't really noticed it. Aside from calling my various financial institutions and utilities to change my phone number with them, it's pretty status quo. We were already watching most of our stuff on demand or through online services anyway.

If you'd like to know what I did or how I did it, I documented the whole plan. I'll do a blog entry later for the official release of my media center documentation site, but you can read over there about my cable cutting plan: what we did and the equipment/services we use.

net, vs, ndepend comments edit

NDepend 6 was recently released with a ton of new features. I've been working with NDepend for quite some time (my earliest blog entry on it was for version 2.7) and every release gets better. It's been a couple of years since version 5 came out. What's new?

The first thing you notice that's new when you start things up is the additional integrations they've added. It used to be just "install the extension for Visual Studio" but now there are icons for TFS, TeamCity, SonarQube, and Reflector integration.

NDepend 6 integrations

I'm particularly interested in the TeamCity integration because that's the build server I use. I have manually integrated it in the past using MSBuild and some manual TeamCity configuration, but with the new add-in, I can just drop NDepend on the build server and have all that work done for me. There's even a specific NDepend build step type added and the report magically shows up in the dashboard. There are some great step-by-step walkthrough videos on the NDepend site showing how to set this up.

I decided to analyze some of the new code I've been working on. It was pretty easy to get my project started. I love how NDepend helps you figure out where to go next if you haven't used it before.

NDepend beginner dialog

The report has improved by adding "how to fix" information to rule failures. One of the challenges I've had in the past is that you could see what things might have failed a rule, but you didn't really have anything clearly "actionable" you could tell folks to fix. You had to kind of "know" what a rule meant. Now there's no guesswork.

Report showing how to fix violations

One of my huge complaints with other tools (coverage, analysis) has been addressed - handling of async/await methods. A lot of what I've been working on lately has been Web API code, which is async/await from the ground up. Have you ever looked at that stuff in a decompiler like Reflector? Or a code coverage tool? I've found you don't get any information on it ("Let's just omit it!"); you get incorrect information on it ("You don't have full coverage because you didn't cover all the cases in the generated state machine!"); or you get confusing information ("I'll show you all of the compiler generated methods that don't make sense!").

Reports are very clean and complete, but you don't see the compiler generated state machine junk. Finally!

The metrics view just doubled in value by adding a second "dimension" to its display. You used to be able to just change the size of an item in the view based on a specific metric; now you can compare one metric to a second metric by adding a sort of "heat map" style coloration to it.

My favorite combination so far is to set the box size by "# IL Instructions" and set the color of the boxes by "IL Cyclomatic Complexity." It gives you a pretty good indication of things that need to be refactored - just look for the huge red boxes!

NDepend metrics view

My favorite new feature is the shareable rule files. We have a standard FxCop ruleset we use on all of our projects. We have a standard StyleCop ruleset we use on all of our projects. We can finally have a standard NDepend ruleset we use on all of our projects.

You can create a rule file with all of your analysis rules stored outside the project file and then tell projects to reference the central/common NDepend rules file.

Create a rules file

Once you have a custom rules file, you can reference it from your project. You will probably want to switch the paths in your project to be relative to the project file so it works on your machine and the build server.

Change paths to relative

With every iteration, NDepend just gets more compelling. I get so much insight from it about our code and areas we need to improve - things that are hard to see when you're neck deep in code and NuGet package references and under a deadline. You owe it to yourself to check it out.

Full disclosure: I got a free personal license from Patrick at NDepend. However, we have also purchased several licenses at work and make use of it to great benefit.

lastpass, security comments edit

I use LastPass for a lot of things including storing my personal software license files. I use the "secure note" function to save the license information and attach the license file to the secure note.

I was working on something today and trying to save a license to my machine and kept getting a dialog saying, "Error opening attachment. Error C." Nothing really specific and very confusing. I was able to save the attachment from the LastPass web site but not through the browser extension.

I ended up finding the solution in this forum post.

  1. LastPass Icon > Tools > Advanced Tools > Clear Local Cache
  2. LastPass Icon > Tools > Advanced Tools > Refresh Sites

After doing a clear and refresh, the attachment saved correctly. These are probably good steps to try whenever you get any sort of error with the LastPass browser extensions. Filed for future reference.

vs, coderush comments edit

CR_Documentor version 4.0.0 has been released to the Visual Studio Gallery and adds support for Visual Studio 2015.

Head over to the gallery to get your copy or get it through "Extensions and Updates" in the Visual Studio "Tools" menu.

Note: In VS 2015 RC you may notice that after installing the add-in the only add-in that shows up for CodeRush is CR_Documentor. I'm not sure why this is, but it seems to be fixed by clearing out the files in your loader cache in these folders:

%appdata%\CodeRush for VS .NET\1.1\Settings.xml\Loader
%appdata%\CodeRush for VS .NET\1.1\Settings.xml\_Scheme_FrictionFree\Loader

It is safe to delete these files because they will be re-created on the next restart of VS. This will get all the CodeRush features to show up again.

I filed an issue with DevExpress about this. If you are having this problem, please add a comment to that issue so they know it's not just me.

media comments edit

Back in March 2014 I started converting my DVD rips into MP4 files for use with Plex. I ran two laptops (both with 2.3GHz dual-core CPUs) 24/7 until early March 2015 when I added a third computer - an eight-core 4GHz machine.

Today I finally finished converting all of my disc-based video content to MP4.

Some quick statistics:

  • Total number of files: 4998
  • Total content runtime: 134 days, 8 hours, 56 minutes, 47 seconds
    • SD runtime: 115 days, 12 hours, 25 minutes, 17 seconds
    • HD runtime: 18 days, 20 hours, 31 minutes, 30 seconds
  • Total file size: 5182.3GB
    • SD file size: 3042.04GB
    • HD file size: 2140.26GB
  • Average MB/minute for SD content: 18.73
  • Average MB/minute for HD content: 80.72

I'm pretty pleased with how everything has come together. Seeing it all in Plex, nicely organized... it's a good feeling.

I can definitely say CPU power is important in video conversion. My laptops could convert an average SD movie in three or four hours, but an HD movie... I couldn't get one converted in a day. The eight-core behemoth can take the same SD movie and finish in an hour or less; and HD movies take about four hours - same as SD content on my laptops.

Anyway, if you're looking to convert a bunch of video, it's worth investing in some hefty CPU power. It'll save you tons of time.

Finally, as part of this, I'd like to introduce my media center documentation on ReadTheDocs.

It's a work in progress, so this is sort of a "soft launch," but I think it's fleshed out enough to be of some use. I will probably do a more dedicated blog entry for it when I've got more of it filled out.

Information about how I converted my stuff with Handbrake, including the script I used to pull the report data above, as well as the specs for my behemoth conversion/Plex server, is all over there.

process, security comments edit

I feel like I should write a book. It'd be epic like Moby Dick but would start with, "Call me Yossarian." This is going to sound confusing and comedic, straight out of Catch-22, but I assure you it's entirely true. It is happening to me right now.

Serenity Now!

We write a lot of documentation to a wiki at work. I've got permissions on it to add pages, rename pages, move pages... but not delete pages. If I want to delete a page, I have to find someone who has delete rights and ask them to do that, which doesn't make sense because I'm a pretty heavy contributor to the wiki.

I decided to seek out delete permissions for myself.

The wiki is managed by an overseas team. The previous process to get permissions to the wiki was to send an email to their infrastructure distribution list with your request and the issue would be dealt with in a day or two. It was fairly effective from a customer perspective.

The new process to get wiki permissions is to file a ticket in this custom-built ticketing system they've adopted. You find this out by sending an email to the infrastructure distribution list and reading the "out of office" autoresponder thing that comes back.

You can't file a ticket unless you have an account on the ticketing system. That's... well, not unheard of, but a bit inconvenient. Fine, I need to create an account.

In order to get an account on the ticketing system, you need to file a ticket. No joke. As one colleague put it, this is sort of like a secret society - you can't get in unless you already know someone who's in and will "vouch for you" by creating a ticket on your behalf.

Three working days later, I have an account so I log in. The ticketing system is a totally custom beast that was initially written starting in 2001 and hasn't really been updated since 2008. It looks and behaves exactly like you think - it's very bare-bones, there's no significant help, and it's entirely unintuitive to people who don't already use it every day.

Seeking out help, I notice in the autoresponder email there's a wiki link to a guide on how to file tickets. Cool. I visit that link and... I don't have permissions to see the wiki link.

In order to see the guide on how to file tickets, I have to file a ticket. Of course, I'm not sure what kind of ticket to file, since I can't see the guide.

I search around to see if there's any hint pointing me to which ticket type to file since they all have great titles like "DQT No TU Child Case." Totally obvious, right? I end up stumbling onto a screen shot someone has taken and posted to a comment section on an unrelated wiki page referring me to the type of case I need to file.

I don't see the right case type on the list of available tickets I can file. Turns out I don't have ticket system permissions to file that kind of ticket.

I have now opened a ticket so I can get permissions to open a ticket to get permissions to delete pages from the wiki. This is after, of course, the initial "secret society" ticket was filed to get me an account so I can file tickets.

humor, rest comments edit

I was browsing around the other day and found your mom's REST API. Naturally, I pulled my client out and got to work.

An abbreviated session follows:

GET /your/mom HTTP/1.1

HTTP/1.1 200 OK

PUT /your/mom HTTP/1.1

HTTP/1.1 402 Payment Required

POST /your/mom HTTP/1.1

HTTP/1.1 411 Length Required

PUT /your/mom HTTP/1.1

HTTP/1.1 406 Not Acceptable
HTTP/1.1 413 Request Entity Too Large
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 502 Bad Gateway
HTTP/1.1 503 Service Unavailable

I think I need to get a new API key before she gives me the ol' 410. :)