TL;DR: This article talks about an app startup error that can happen with Metro Style apps in Windows 8, how the presence of an app.config file can prevent the app from starting and how the Windows event log viewer’s new Immersive-Shell section can help.
The Windows 8 Metro style Xaml/C# application development is an interesting experience.
Since .NET is merely on top of a WinRT and its native structure, you’re left in a bit of a darkness sometimes, when it comes to debugging problems that come from WinRT.
Silverlight and Windows Phone also have their fair share of blind issues of this kind, either by having the application that exits with no apparent reason (when it is in fact a StackOverflow) or because you’ve set two namespaces names with the same content.
You’ve basically left at guessing, particularly on Windows Phone and Silverlight for the desktop, and if you’re lucky enough you’re having a error code that specific enough so that you can narrow your solution to a dozen google can find for you. If you’re not, well you’ve got a E_ERROR. Fail, as they say.
Windows 8 is actually a bit better at that, because of the Event Viewer. There’s a lot of details that appear there, and it’s very informative.
This article describes a bit of what NuGet does and why you should take a look at it, but also a package installation customization to a work around a problem with packages that contain optional assemblies.
NuGet is a fantastic tool. Its ability to ease package discovery, installation and update is a big time saver. As a solution maintainer, you can spend less time deploying and updating your external dependencies, particularly when they’re often updated.
Private NuGet Repositories
It can be used to easily install public packages exposed via Microsoft’s servers, but it can also be used to create private package repositories.
I've been using it to publish internal framework that is often updated and used in many projects. The automatic creation of packages in a build script and the ease of deployment using the NuGet OData server is, again, a big time saver.
Each time a check-in is performed to update the internal framework, a new package is automatically created and it appears as a package update for the projects that use it.
Existing libraries and NuGet
The package model is built around some basic rules:
- Each package is installed using its version as the directory name
The NuGet engine will update all the references “HintPath” nodes of projects files for them to point to the updated package location.
- By default, the install action of a package adds references to all the available assemblies in the target project.
There’s a pretty good reason for that; you don’t want to download and install assemblies that you don’t need. There is no support for “sub-packages”, even with reference exclusions. Big frameworks, like Enterprise Library, get chunked into small dependent packages, and you can install only those needed by your projects.
- A project that installed a package that has references to package-excluded references will not have these manual references updated to the latest package.
That is a side effect of the second rule. If you add reference-excluded assemblies to a package, the action of updating that package will not update manual references you created by referencing these assemblies.
For existing libraries that may not easily be split into small pieces, primarily for time constraints, moving to NuGet can be a tough job. If you make a package with all your assemblies and only reference a few of them by default in there, then updating the package can quickly become an annoying “Find and Replace” job to manually change references that did not get updated automatically by the NuGet engine.
Using the Install.ps1 script
Fortunately, there is a file that can be included in the package, which is by convention named and located in tools\install.ps1.
It is a PowerShell script that gets called automatically when the package is installed. But the interesting part is that this installer file gets called with a DTE.Project instance that can be used to manipulate the actual project in VS2010 !
This means that when the package is installed, it is possible to update the references that were manually created to the previous package assemblies.
Updating the manual references
This is not a straightforward as it may seem, but after working around a HintPath update issue, here is a small helper to do the job:
param($installPath, $toolsPath, $package, $project)
$packageName = $package.Id + '.' + $package.Version;
$packageId = $package.Id;
# Full assembly name is required
Add-Type -AssemblyName 'Microsoft.Build, Version=126.96.36.199, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
$projectCollection = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection
# There is no indexer on ICollection<T> and we cannot call
# Enumerable.First<T> because Powershell does not support it easily and
# we do not want to end up MethodInfo.MakeGenericMethod.
$allProjects = $projectCollection.GetLoadedProjects($project.Object.Project.FullName).GetEnumerator();
foreach($item in $allProjects.Current.GetItems('Reference'))
$hintPath = $item.GetMetadataValue("HintPath")
$newHintPath = $hintPath -replace $packageId + ".*?\\", "$packageName\\"
if ($hintPath -ne $newHintPath)
Write-Host "Updating $hintPath to $newHintPath"
This script is called for each project the package is installed onto, and scans all the references of the project that match the current package to update them.
You’ll notice that the ICollection<T> interface is not particularly PowerShell friendly. Too bad the Powershell syntax does not allow the use of generic methods, otherwise that nasty GetEnumerator / MoveNext could have gone away. Still, Powershell is dynamically typed so using IEnumerable.Current is fine.