net comments edit

I’ve been working struggling with WiX for the last few days and I feel like it’s mostly for two reasons:

  1. WiX assumes you know MSI. That is, Windows Installer XML is a thin veneer over Microsoft Installer technology, not an abstraction layer for it. I think this is a faulty assumption. While I understand WiX isn’t meant to teach you MSI, if I’m building a new installer and I want to try WiX out, I’m probably not thinking, “Oh, I should go read the entire MSDN library about MSI first.” I’m actually thinking, “I’m building a new installer, I’m building it in WiX, and I should be able to read the WiX documentation or find WiX examples that show me how to do that.”
  2. WiX documentation is thin. I think this is the result of the faulty assumption in item #1. There is very little linking from the WiX documentation back to the corresponding MSI docs on MSDN so you’d never know that the construct on this WiX page corresponds to this MSI concept. Examples are few and far between. The one tutorial out there assumes you’re building everything by hand and doesn’t really cover the Visual Studio integration that I’m sure people have picked up by now.

I’m guessing there are three schools of thought going on when it comes to contributing to WiX documentation:

  • I already know how this works so everyone else must already know as well.
  • The “smart user” can go “check out the source and figure it out” so that’s good enough.
  • I’ve just struggled for the last week trying to get this to work and now that it does I’m too exhausted and frustrated to contribute anything back.

I know I fall into that last school: I’ve been screwing around with it for so long that, now that it works, I really just want to jump ship and be done with WiX until the next time I have to add something to the installer. Couple that with the fact that, really, while the installer works, I don’t know that what I did was “right,” just that “it works.” It feels very “duct tape and baling wire” so I’m not confident that any contributions I might make to the docs would be the way people should be doing things, just the way I got them working.

Maybe “it works” is the same as “the right way” in installer land? Hmmm. I’ll have to think about that. But I digress.

All that leads me up to a list of things I’d love to see in WiX documentation.

  • A disclaimer on the front page saying “you need to know MSI.” Buried a couple of pages down they mention that “in order to fully utilize the features in WiX, you must be familiar with the Windows Installer concepts.” I don’t think that’s quite accurate. On the front page of the site, and on the front page of the docs, there needs to be some big, bold, red, flashing sign that says, “If you don’t know MSI, STOP HERE.” OK, maybe not exactly that, but something up front to set my expectations that I need to know a little something about MSI before I can understand WiX. Either that, or all of the WiX docs need to be updated to stop making that assumption. (I like that better, but I know it’s not realistic.)
  • A complete table of contents or index of all help topics. If you go to the main documentation page, you’ll see a fairly short table of contents. Say I want to add a dialog to my installer that gathers some information from the user. Which topic is that under? “How To Guides?” Nope. “Fundamental Tools and Concepts?” Nope. I don’t actually know. Any documentation I was able to find about user interface stuff was through the search box. And since there’s very little cross-linking from concept to concept, I don’t actually know if what I found was what I should have been finding. (Interestingly enough, it appears there’s sort of a one-way warp going on with the table of contents. For example, this page “Customizing Built-in WixUI Dialog Sets” shows, at the top, that it falls under a “Modifying the Installation User Interface” topic, which is under “Creating Installation Packages.” If you look at the “Creating an Installer Package” page, there is no link at all to the “Modifying the Installation User Interface” topic. That whole tree is orphaned.)
  • Screen shots of all of the standard dialogs. There is a page that describes the “standard dialog set” that comes with WiX and there are textual descriptions of each of the dialogs… but there is no picture of them, so if you’re troubleshooting your installer, you need to sort of… guess… which dialog you’re looking at. Screen shots would really help to visually identify the dialogs.
  • Flow charts of the standard UI. Once you figure out how to get a UI into your installer, you’ll probably want to modify it. Maybe you’ll want to add a new dialog into the flow. Except… what’s the flow? Where do I insert my dialog? I have to know the ID of the dialogs between which I want to insert my custom dialog but there’s no way to find that out. At least, none that I could figure. It was trial and error for me.
  • Tips on troubleshooting and debugging. If I get error 2819 in my installer, what the hell is that supposed to mean? I know WiX is just a veneer over MSI and I don’t expect them to reproduce the MSI documentation, but a little “here’s how to troubleshoot issues in your installer” doc would be helpful. Can I add tracing somehow? Can I attach a debugger? What facilities are available to me? Even if there are none, a doc saying “you’re screwed” and a link to the error codes on MSDN would be helpful. Maybe some common solutions to common problems… if there are common problems.
  • More cross-linking with relevant MSI documentation. The WiX documentation reads like it’s standalone, but it’s really not. For every document on there, there’s at least one corresponding page of MSDN documentation about MSI that would be helpful. Unfortunately, the only place you really see links to MSI docs are off the “fundamental concepts” page, and even then, there are only three links… and one is just to “the Windows Installer 4.5 SDK.” Not so helpful.
  • More advanced how-to guides. Most of the guides on the site - and on the web in general - are “basic guides.” You know, “here’s how to install that EXE you built that has no dependencies, no configuration settings, and doesn’t need anything set in the registry or put into the GAC.” I’m not sure about the major WiX use case, but I don’t think an application that simple even needs an installer, let alone something written in WiX. I’m guessing that folks who have decided to go the WiX route are interested in the more intermediate and advanced scenarios. “I need to install a web site that has a database connection string that needs to be set at install time.” “I have a Windows service to install and it needs to ask for service credentials during install and maybe whether it should run on startup or manually.” Good luck with that.
  • Rich examples, particularly around UI customization. One of the things I needed to do in my installer was add a custom dialog to get some data from the user about web site parameters (port number, app pool info). I want to reuse that dialog (sort of like the “Browse for Files” dialog) in different installers and may have to use it multiple times in one installer, sort of like calling a function - a “parameterized” dialog, if you will. This is easy to do in Windows forms apps. Figuring out how to create the dialog, wire it into the flow, send up the right button events, putting that together with “indirect properties,” and so on… it was a nightmare. I found a few reasonable examples of how to set up non-UI related items, but almost nothing except two-or-three line snippets when it came to UI. Even in the UI examples, they didn’t make sense. For example, when you look at an installer, the user gets asked for custom parameters after they choose a Typical/Custom/Complete install… but all of the examples insert dialogs before that choice. Admittedly, it’s easier to do that, but it’s not what you should be doing. Where are the examples that show it the right way? This goes hand-in-hand with the more advanced “how-to” guides idea, above.
  • More information about web application deployment. WiX appears to be great about deploying, say, a console application, but if you follow the simple setup example they provide but use a web application instead of a Windows forms application, you’ll find the installer deploys your .dll into the root of the web app, not in the “bin” folder where it should be. How do you fix that? I posted my solution, but there is literally nothing about differences in deploying web apps from other app types. The closest it gets is documentation about “Iis Schema,” which is the extension that allows you to create IIS applications. Usage? Bah! Examples? No way, man. Just schema. Go Google for samples or blog posts if you want more. (Oh, and there’s no way I can tell that you can create an IIS7 application pool with .NET 4 and an integrated pipeline. Guessing that hasn’t made it in yet.)

I think WiX is a pretty powerful thing. I think it could help out a lot of people if it was more easily grasped - there’s a hell of a learning curve on it. I think they could get there if there was some time spent augmenting the docs.

(Dear Wrox: There’s totally a book opportunity here. There is only one book I could find on WiX, it’s from 2004, and several of the reviews claim it as “incomplete” or “not deep enough.” I’d totally buy a more recent, more complete book.)

dotnet, ndepend comments edit

I was fortunate enough to get my hands on a license for NDepend 3 so I decided to take it for a spin. I’d had some experience with NDepend 2 and thought it would be interesting to see the new, cool stuff.

Install is still reasonably easy. It’s still just a zip file - unzip, drop your license XML file in the folder along with the application, and you’re up and running. That said, one of the things that’s changed since I last wrote about NDepend is that my development environment is as a non-admin user on Windows Server 2008 R2 with the User Account Control turned on. In that scenario, it’s not quite as simple as unzip and go if you want to put the application in the Program Files folder as is recommended. The steps I had to go through:

  1. Unzip the program to a folder on my desktop.
  2. Copy my license XML file into that folder.
  3. Use the streams tool from Sysinternals to unblock all the files.
  4. Copy the folder from my desktop to the Program Files folder. (This will ask for admin credentials.)
  5. Create a folder at C:\ProgramData\Microsoft\Windows\Start Menu\Programs\NDepend so I can have a shortcut to the program in the Start Menu. (This will ask for admin credentials.)
  6. Create a shortcut to VisualNDepend.exe on my desktop (because you can’t create a shortcut directly in the Start Menu).
  7. Move the shortcut from the desktop to the folder I created in the Start Menu. (This will ask for admin credentials.)

So, not insurmountable, but more than a single step. It would be nice if there was an actual installer that did all this for me in a future version of NDepend.

The first thing I noticed was a slight update in the welcome screen that made installing the Visual Studio and Reflector add-ins a little more prominent.

NDepend welcome
screen.

Clicking on one of the install buttons will bring you to the respective place in the options dialog for Visual NDepend. Click “Install” and things “just work,” which is awesome:

NDepend options screen for installing the Visual Studio
plugin.

I noticed that the Ribbon is still not the default interface used by NDepend, so you’ll want to go into the options and specify to use Ribbon rather than regular menu/tool bars. The Ribbon is still easier to figure out.

NDepend options for selecting an interface
choice.

The project I chose to analyze this time was Autofac, the open source dependency injection framework.

From the Visual NDepend welcome screen, I clicked the “Create Project…” link and I got a small dialog to fill out:

New NDepend Project
dialog.

That gets you to the project properties window.

New project properties window, ready for assemblies to be
added.

Something I noticed when taking screen shots is that the smallest I could make the window and still have all the buttons visible was about 1200 pixels wide. If you’re running in a lower resolution monitor, you may be out of luck. Something to consider.

The first thing I noticed (sort of by accident) was this little icon in the corner of the window…

Informational icon in the bottom right corner of the NDepend
window.

I’m not sure if it was there in the last version of NDepend or not, but it’s cool. Hovering over it tells you what’s going on:

Hovering over the info icon gives you feedback on what you should do
next.

It’s sort of like a little “what do I do next?” cue. Very nifty.

I clicked the “Add Assemblies of a Visual Studio Solution” button and selected the Autofac core solution.

"Add Assemblies of a VisualStudio Solution"
button.

After removing all of the unit test assemblies and demo project assemblies, I was left with some errors. As it turns out, NDepend wasn’t getting the assemblies from their target folders - it was trying to get them from the bin folders of some of the demo projects.

To fix this, I had to do two things.

First, I rebuilt the solution to make sure the assemblies to analyze were in the associated build output locations (bin\Debug for each).

Second, I had to click the “View Folders” button, switch to “relative path mode,” and delete the folders from the test and demo assemblies.

Viewing and fixing up the folders for a
project.

Side note:I still think things should default to “relative path mode” because if you’re going to share the NDepend project with other team members and check it into your source tree, you don’t want to be using absolute paths. I also found itpretty unintuitive that the target .NET framework version was only revealed as an option when you opened up the folder view. I don’t feel like it has anything to do with folders. But I digress.

Once I did that, all of the target assemblies were properly located.

Target assemblies
fixed.

The next thing I noticed was that the MVC 2 assembly, referenced by one of my targets (Autofac.Integration.Web.Mvc) wasn’t found.

Dependency error - System.Web.Mvc can't be
located.

To fix that, I had to open up the folder view again and add a new search folder to C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 2\Assemblies - where System.Web.Mvc.dll is located. That’s when I ran into a problem:

NDepend keeps the .NET Framework search folders as absolute paths regardless of whether your project is in “relative path mode,” but in “relative path mode” you can’t add a new absolute path folder yourself. You also can’t add a new “framework location” so it knows to search for it next time. That means, for the MVC 2 assembly, unless I keep a local copy in my project’s source, there’s still no way I can share this project with my team. Why? Because in relative path mode, I may check my project out in a different location on my drive than other team members and the relative path to the MVC 2 assembly will break. Problem. I even tried manually hacking the project file. It sticks as long as you don’t open the project up in Visual NDepend again, at which point it switches everything back to absolute paths.

The folder list after adding a location for MVC
2.

For the sake of this article, we’ll move past that. Hopefully this will be fixed in a future version because it’s sort of a showstopper for adding NDepend to continuous integration on MVC projects.

The thing about this is, it looks like it was a painful process but it wasn’t that bad. There were a couple of hiccups, but all of this took just a couple of minutes. It just wasn’t quite as easy as I think it should be. That said, once you have it all set up, you don’t have to do it again - just reuse the project file next time you want to run analysis.

Once I had the MVC 2 assembly located, everything was found, so I hit the big green ‘Run Analysis’ arrow and let it roll!

When it was done running (it only took a few seconds), I got a report that popped up in my browser.

Header from the HTML report that pops up after NDepend
analysis.

There is a ton of information in this report including notes on methods you should look at refactoring (e.g., things that take too many parameters) and so on. In many cases, the warnings that come up are very similar to things you’d see coming out of FxCop, but with a more in-depth analysis. For example, NDepend can tell you about methods that are poorly commented:

Definition of the CQL query showing not enough
comments.

It also includes some really cool diagrams, like “abstractness vs. instability”:

Abstractness vs. Instability
graph.

In this case, Autofac looks pretty good! You can also see a diagram showing the dependency graph between assemblies:

Assembly dependency
graph.

Again, reasonably clean for Autofac.

Flipping back to the Visual NDepend UI, you can see the same information but can navigate around in an interactive fashion.

Navigating a report visually in
NDepend.

For example, I looked at the Code Quality section of queries and looked at the list of methods that are considered too big from a “number of lines of code” standpoint. In Autofac’s case, there is just one: Autofac.Configuration.ConfigurationSettingsReader.Load. Clicking that, I can see a lot of information about the method:

Detailed method info
view.

Double-clicking on the method will open up the source file in Visual Studio so I can see it for myself. Or I can right-click on the method and open it up in Reflector (which is faster than viewing source in VS). (You can use the NDepend options to switch your source editor tool to something like Notepad, which is a good idea. Do that. It makes opening source files much faster.)

There is a lot to look at. Very interesting stuff that’s well worth checking out.

One good way to get this going for your team is to integrate it with your continuous integration build. After you run your FxCop analysis and unit tests, run NDepend and integrate the report into the dashboard. It’ll help get people familiar with some of the things to look for and keep them mindful of their development. It sort of sucks to see code you wrote show up as failing some of the “code quality” queries, believe me.

One shortfall of the build integration with NDepend is that there are only two levels of query: WARN and SELECT. WARN queries will output a build warning; SELECT queries just introduce information into the report. Neither one necessarily fails the build. It would be nice to have ERROR query types, too, to allow you to fail the build. I’ve mentioned this to the folks at NDepend before and it was going to be “considered” but it’s not there yet.

Especially for larger teams where you probably have a technical lead or architect looking at statistics and making decisions about how to design things, this is a fantastic tool. For the average team member, you’ll probably look at the report occasionally, but you probably won’t run the reports all the time or anything. On the other hand, integrated into the build and with someone sort of looking at the overall direction of the project, this becomes exceptionally powerful.

Head over to NDepend and check it out. It’s well worth your time and better than ever.

dotnet, build, aspnet comments edit

MSDeploy is a pretty cool installer technology, but it’s not what everyone uses, and my personal experience so far is it’s not flexible enough for me. I’m not the biggest fan of Windows Installer, either, but you can’t say it isn’t flexible.

As part of a recent project, I was working on a web site installer. I wanted Wix to take my web site - including the transformed web.config files and such - and package it into an installer. I’m no Wix expert, but this didn’t appear to be as straightforward as you might think.

The usual way you consume project output (when using the Visual Studio integration and .wixproj files) is to add a project reference to the application project, set up the output you’re interested in grabbing, and telling Wix to “Harvest”:

Normally 'Harvest' is 'True' and 'Project Output Group' is set to
something.

If you do that for a web project, though, the installer ends up dropping the web project assemblies right in the root of the app instead of keeping them in the bin folder like they’re supposed to be. I understand why it’s doing that (because other app types would actually need it that way) but for web projects it’s wrong.

Not only that, but you know that whole fancy web.config transformation thing you can do when you use MSDeploy? Wix doesn’t do that transformation. I want that, so I figured out how to do it:

You can get Wix to automatically consume MSDeploy-staged output from a web project. It just takes a little manual hacking to get it to work. Not much, but it is manual.

First, add a project reference from your Wix .wixproj to your web project. In Visual Studio, set the properties on that project reference - set “Harvest” to False and “Project Output Group” to “None.” If you look at the .wixproj source, that reference will look something like this:

    <ItemGroup>
      <ProjectReference Include="..\..\UI\UI.csproj">
        <Name>UI</Name>
        <Project>{YOURGUID-HERE-abcd-abcd-abcdabcdabcd}</Project>
        <Private>True</Private>
        <DoNotHarvest>True</DoNotHarvest>
        <RefProjectOutputGroups>
        </RefProjectOutputGroups>
        <RefTargetDir>INSTALLLOCATION</RefTargetDir>
      </ProjectReference>
    </ItemGroup>

Once you have that, it’s time to do a little manual hacking.

Open up the .wixproj in a text editor. Find the ProjectReference you just added. Just before the end of the ProjectReference, add a metadata property called “WebProject” and set it to “True” like this:

    <ItemGroup>
      <ProjectReference Include="..\..\UI\UI.csproj">
        <Name>UI</Name>
        <Project>{e3362c3d-45c4-47d3-ad61-9f6fbcad9b02}</Project>
        <Private>True</Private>
        <DoNotHarvest>True</DoNotHarvest>
        <RefProjectOutputGroups>
        </RefProjectOutputGroups>
        <RefTargetDir>INSTALLLOCATION</RefTargetDir>
        <WebProject>True</WebProject>
      </ProjectReference>
    </ItemGroup>

This will set web projects apart from other projects - in case you have multiple project references going. This is how you can identify which ones are web projects that needs to be staged.

Now look in the .wixproj file and find a Target node with the Name “BeforeBuild” - there may or may not be one, depending on your project, so if there isn’t one, create one just above the closing </Project> node at the bottom of the file. You may even see a little comment that is there telling you where to place the Target. The empty Target will look something like this:

        <!-- ...here's your project reference... -->
        </ProjectReference>
      </ItemGroup>
      <Import Project="$(WixTargetsPath)" />
      <Target Name="BeforeBuild">
      </Target>
    </Project>

The magic goes inside the BeforeBuild target. What you want to do there is:

  • Use the MSDeploy stuff to “stage” the web site with all of its transformed configuration files and everything.
  • Tell Wix where the staged output is.
  • Tell Wix to generate a Wix source file that includes the entire staged web site contents.
  • Do this for all of the project references that are marked as WebProject = True.

That’s done with just a few lines of MSBuild script:

    <Target Name="BeforeBuild">
      <MSBuild
        Projects="%(ProjectReference.FullPath)"
        Targets="Package"
        Properties="Configuration=$(Configuration);Platform=AnyCPU"
        Condition="'%(ProjectReference.WebProject)'=='True'" />
      <ItemGroup>
        <LinkerBindInputPaths Include="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\" />
      </ItemGroup>
      <HeatDirectory
        OutputFile="%(ProjectReference.Filename).wxs"
        Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\"
        DirectoryRefId="INSTALLLOCATION"
        ComponentGroupName="%(ProjectReference.Filename)_Project"
        AutogenerateGuids="true"
        SuppressCom="true"
        SuppressFragments="true"
        SuppressRegistry="true"
        SuppressRootDirectory="true"
        ToolPath="$(WixToolPath)"
        Condition="'%(ProjectReference.WebProject)'=='True'" />
    </Target>

(Note that it’s line-wrapped for readability, but in the .wixproj file it’s only five lines in the Target.)

Let’s walk through that:

  • The MSBuild task calls the “Package” target on each of the project references where WebProject = True. The property it passes in for “Platform” is AnyCPU because it’s a platform target that pretty much everything knows about by default. It’s important to specify a platform that all of the projects in your solution know about because that way project-to-project references will work. If you specify a platform that not every project knows about, you have to specify an OutputPath folder so the task can locate project-to-project build output locations… and that just gets messy. Stick with AnyCPU and make your life easy. (It also means output will be in expected locations like “bin\Debug” or “bin\Release.”) The “Configuration” value is used not only in figuring out where to build the staged output but also in your web.config transforms - that’s how it knows which transform to use. Finally, you’ll see the Condition on the MSBuild task - that’s how we make sure to only run this for web projects.
  • The ItemGroup sets up an item for Wix. Wix needs to know where the staged output base path is. The Package target builds its staged output by convention. It goes in a folder called: obj\[Configuration]\Package\PackageTmp under your web application. (Again, sticking with “AnyCPU” as the platform value means you’ll have a predictable output location.) “Configuration” gets substituted in with the “Configuration” variable you passed into the MSBuild task. So if you were building the Debug configuration of an application in C:\MyWebApp, the Package target would build to: C:\MyWebApp\obj\Debug\Package\PackageTmp The crazy long MSBuild-script-variable string you see there builds up the location of the Package output using that convention.
  • The HeatDirectory task builds the Wix source from the Package output. The file it builds will match the name of the ProjectReference, so if your web application is called “MyWebApp.csproj” then the Wix script it builds will be “MyWebApp.wxs.” The Wix component it builds (which you’ll need to know so it can be included in the main install script) is also named after your web application by adding a “_Project” suffix (e.g., “MyWebApp_Project”). You’ll see, again, the Directory we specify is that big long package output folder. And, finally, you also see that the Condition on the task makes sure we’re still only running this for project references where WebProject = True.

When that target runs, you’ll see a .wxs file pop out in the .wixproj project folder. Add the generated .wxs to your .wixproj project so it knows to include it in the build.

Add the .wxs file to the
.wixproj.

Finally, in your main Product.wxs file, add a ComponentGroupRef to the Feature that should install your web site and use the generated “ProjectName_Project” (e.g., “MyWebApp_Project”) component ID, like in this fragment:

    <?xml version="1.0" encoding="UTF-8"?>
    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
      <Product Id="YOURGUID-HERE-abcd-abcd-abcdabcdabcd" Name="YourProduct" ...>
        <Feature Id="YourFeature" Title="Your Feature" Level="1">
          <!-- Include your generated components here. -->
          <ComponentGroupRef Id="UI_Project" />
        </Feature>
      </Product>
    </Wix>

That’s it! (Actually, that wasn’t a small amount of work, but it’s not as hard as some things in Wix.)

Now don’t forget to set up the web site in IIS (that’s not done for you by the above - only getting the files into the installer). Good luck!

UPDATE 8/6/2010: I ran into an issue where a web project that has a project-to-project reference to a non-web project (e.g., a web project that references a class library as a .csproj rather than a .dll) may look in the wrong spot for the class library. I updated the article to accommodate for this. The change is thatif you specify AnyCPU as the platform, you don’t have to specify an output folder and things magically fall together.

UPDATE 3/8/2013: Updated code snippets for Wix 3.8, which brought some breaking changes. The MSBuild “BeforeBuild” snippet uses an ItemGroup with an item called LinkerBindInputPaths for the project package location instead of a PropertyGroup with a property called LinkerBaseInputPaths. Also, in the Product.wxs snippet, the reference to the Product.Generated component is removed since that is off by default in Wix 3.8.

gaming, xbox comments edit

My Xbox 360 profile was on a 512MB memory unit and with the USB flash drive update to the system, I figured it was time to move on up.

Xbox 360 has some sort of “test” it runs USB drives through to determine if the drive “meets recommendations” or is “below recommended performance.” If it’s below the recommended performance, you’ll supposedly get degraded experiences in loading/saving games, reading your profile information from the drive, etc. Unfortunately, the Xbox 360 storage page really doesn’t tell you which drives work other than their Xbox 360 branded drives.

To that end, I tried a couple of drives and found one that worked (the Lexar JumpDrive Firefly) and one that didn’t (SanDisk Cruzer). I figure I’ll put that info here, and if there are people who have experiences they want to contribute, I’ll add it. Send me a link to the drive on Amazon or whatever and whether or not it “met the recommendations.”

Prices listed are current as of the day I added the drive to the list.

Meets Recommendations:

Size Drive Price Link Date Added
16GB SanDisk Cruzer Fit 16 GB USB Flash Drive SDCZ33-016G-B35 $12.19 Amazon 7/8/2013
16GB Lexar JumpDrive TwistTurn 16 GB USB 2.0 Flash Drive LJDTT16GASBNA $12.98 Amazon 11/1/2012
16GB Corsair Flash Voyager 16 GB USB 2.0 Flash Drive CMFUSB2.0-16GB $15.00 Amazon 5/10/2012
16GB PNY Mini Attaché 16GB USB 2.0 Flash Drive P-FD16G/MINI-EF $17.00 Amazon 2/21/2012
16GB Lexar JumpDrive TwistTurn 16 GB USB 2.0 Flash Drive LJDTT16GASBNA $22.99 Amazon 8/8/2011
16GB Kingston DataTraveler C10 $30.99 Amazon / NewEgg 7/29/2010
16GB Lexar JumpDrive Firefly LJDFF16GASBNA $39.22 Amazon 7/29/2010
16GB Patriot Xporter XT Boost PEF16GUSB $42.99 Amazon / NewEgg 7/29/2010
16GB SanDisk Xbox 360 Drive $57.85 Amazon 7/29/2010
16GB Sony USM-16W/B 16GB MicroVault Compact Metal USB Flash Drive     8/18/2014
8GB SanDisk Xbox 360 Drive $31.45 Amazon 7/29/2010
8GB Kingston Digital DataTraveler 100 Generation2 DT100G2/8GBZ $7.99 Amazon 2/6/2012
4GB Kingston DataTraveler 101 DT101Y/4GB $9.99 Amazon / NewEgg 7/29/2010
2GB Sandisk Cruzer Micro SDCZ4-2048-A11 $25.00 Amazon 5/20/2011

Fails Recommendations:

Size Drive Price Link Date Added
16GB 7dayshop Memory - USB 2.0 Flash / Key Drive £12.99 7dayshop 5/20/2011
16GB SanDisk Cruzer SDCZ36-016G-A11 $37.99 Amazon 7/29/2010
8GB LaCie iamaKey 8 GB USB 2.0 Flash Drive 130870 $26.99 Amazon 12/2/2011
8GB Sandisk Cruzer Micro SDCZ6-8192-A11 $9.99 Amazon 5/20/2011
8GB Dane-Elec zMate Pen USB Drive 8GB Ref DA-ZMP-8192T-R £16.98 Amazon 5/20/2011
4GB Sandisk Cruzer Micro SDCZ6-4096-A11 $6.99 Amazon 5/20/2011
4GB PNY Attache P-FD4GBATT03-EFM1 $7.99 Amazon 5/24/2011
4GB SanDisk Cruzer SDCZ36-004G-A11 $9.99 Amazon / NewEgg 7/29/2010
4GB Geek Squad GS-4GB10 $27.99 Best Buy 8/19/2010
4GB PNY P-FDU4GBSV-EF/GRY Micro Swivel 1 $31.20 Amazon 9/21/2011
? (not reported) Emtec S300 Thin Series $14.49 and up Amazon 1/19/2011

1 The drive failed the original configuration but on subsequent attempts succeeded.

Again, if you find one that works or one that doesn’t, or if you’re using one of the above and can confirm functionality, leave a comment or use the contact link on the site to send me a note and a link to the drive on Amazon or whatever. In the event where someone finds a drive that works and someone else finds that same drive doesn’t work, I’ll probably put it on the “fails” list. Better a drive that works for everyone than one that works for “some people.”

Note: Some folks have found that the first time you plug the drive in and test it, Xbox 360 says the drive passes, but on subsequent tests it fails. I’ll move those drives from the “pass” to “fail” tables as they’re discovered.

autofac, dotnet comments edit

It’s taken some time and a couple of long Google Groups threads, but with a kick in the right direction from Nick Blumhardt, I’ve got multitenant dependency injection working with Autofac and available as a contributed library.

The basic usage pattern is:

  • Determine a strategy by which tenants are identified. That is, which tenant is making a given request? This might come from an environment variable, a request parameter, a role on the user’s principal, or wherever.
  • Build up your application container with the default dependency set. For tenants that don’t override anything, they’ll use these defaults.
  • Create a multitenant-aware container based on the application defaults. This is where the magic of AutofacContrib.Multitenant comes into play.
  • Configure tenant-specific overrides with the multitenant-aware container. Tenants can override things, add new dependencies, or whatever they need to do.
  • Resolve everything out of the multitenant-aware container. All of the resolutions will automatically use your tenant identification strategy so you’ll always get a tenant-specific result.

In practice, it looks like something this:

// First, create your application-level defaults using a standard // ContainerBuilder, just as you are used to. var builder = new ContainerBuilder(); builder.RegisterType<Consumer>().As<IDependencyConsumer>().InstancePerDependency(); builder.RegisterType<BaseDependency>().As<IDependency>().SingleInstance(); var appContainer = builder.Build();  // Once you've built the application-level default container, you // need to create a tenant identification strategy. var tenantIdentifier = new MyTenantIdentificationStrategy();  // Now create the multitenant container using the application // container and the tenant identification strategy. var mtc = new MultitenantContainer(tenantIdentifier, appContainer);  // Configure the overrides for each tenant by passing in the tenant ID // and a lambda that takes a ContainerBuilder. mtc.ConfigureTenant('1', b => b.RegisterType<Tenant1Dependency>().As<IDependency>().InstancePerDependency()); mtc.ConfigureTenant('2', b => b.RegisterType<Tenant2Dependency>().As<IDependency>().SingleInstance());  // Now you can use the multitenant container to resolve instances. // Resolutions will be tenant-specific. var dependency = mtc.Resolve<IDependency>();

The usage is very similar to the existing Autofac usage you know and love.

The multitenancy support works for standard non-web/service apps (e.g., console apps or Windows services), ASP.NET web forms and MVC apps, and WCF service apps.

There’s a ton of documentation about how to use the multitenancy that includes sample code snippets.There are also somesample console, WCF, and ASP.NET MVC applications in the source treeso you can see it in action.

It’s not currently out there as a binary, so you’ll have to do a source checkout and compile it manually, but I’m sure it’ll show up soon. It was released as part of AutofacContrib 2.5.1 and is available for download.

We’re looking for early adopters to give us feedback on it. If you try it out, please let us know what you think in the Autofac Google Group. What did you like? What were the pain points? Did you find a scenario that didn’t work? How was the documentation? The more feedback we get, the better we can make it! Thanks!