Update-Database fails in Package Manager Console on Windows 10 Insider Preview with ambiguous type error


This post is about providing a workaround for this problem until Microsoft provide us with a proper fix.

This problem has been reported here:

There seem to be two types that fail due to ambiguity:

  • Microsoft.VisualStudio.Shell.Package
  • NuGet.VisualStudio.IVsPackageInstallerServices

Yet if you have other failing types in your scenario, understand this post and apply the same logic to your specific case.

Microsoft.VisualStudio.Shell.Package

This workaround fixes the following error:

Type name 'Microsoft.VisualStudio.Shell.Package' is ambiguous, it could be 'Microsoft.VisualStudio.Shell.Package, Microsoft.VisualStudio.Shell.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or 'Microsoft.VisualStudio.Shell.Package, 
Microsoft.VisualStudio.Shell.10.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

To fix this, do the following:

  1. Open Windows PowerShell ISE in admin mode (right click and Run as Administrator)
  2. Open the following file:
    • C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 14.0\COMMON7\IDE\EXTENSIONS\ZPM4HZQB.YOS\Modules\NuGet\Profile.ps1
  3. Go to line number 126 (Ctrl+G and enter the number)
  4. Find this line:
    • $service = [Microsoft.VisualStudio.Shell.Package]::GetGlobalService($ServiceType)
  5. Replace it with these lines:
    • $accel = [psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")
       $accel::add(“specificShell”,”Microsoft.VisualStudio.Shell.Package, Microsoft.VisualStudio.Shell.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”)
       $service = [specificShell]::GetGlobalService($ServiceType)
  6. If your Visual Studio is open, you will need to close it and re-open it, as it caches a copy of this script.

NuGet.VisualStudio.IVsPackageInstallerServices

This is a similar fix to the above, but for this error:

Type name 'NuGet.VisualStudio.IVsPackageInstallerServices' is ambiguous, it could be 'NuGet.VisualStudio.IVsPackageInstallerServices, JetBrains.Platform.VisualStudio.SinceVs11, Version=104.0.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325' or 
'NuGet.VisualStudio.IVsPackageInstallerServices, JetBrains.PsiFeatures.VisualStudio.SinceVs11, Version=104.0.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325'.

To fix this, do the following:

  1. Open Windows PowerShell ISE in admin mode (right click and Run as Administrator)
  2. Open the following file (replace {NuGetPackagesFolder} with the location of your packages folder in your solution:
    • {NuGetPackagesFolder}\EntityFramework.6.1.3\tools\EntityFramework.psm1
  3. Go to line number 1004 (Ctrl+G and enter the number)
  4. Find this line:
    • $packageInstallerServices = $componentModel.GetService([NuGet.VisualStudio.IVsPackageInstallerServices])
  5. Replace it with these lines:
    • $accel = [psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")
       $accel::add(“NuGetInstallerServices”,”NuGet.VisualStudio.IVsPackageInstallerServices, JetBrains.Platform.VisualStudio.SinceVs11, Version=104.0.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325”)
       $packageInstallerServices = $componentModel.GetService([NuGetInstallerServices])
  6. As above, if your Visual Studio is open, you will need to close it and re-open it, as it caches a copy of this script.

The Logic

All I am doing here is quite simple, I am creating a type alias that points to a specific assembly instance, and using that for reference, rather than the version that would resolve into multiple instances.

A Few Notes

The workaround above, particularly the second one, is temporary, and will fail again if you refresh your NuGet package cache before MS come up with a fix for this problem.

Also, since all machines have different configurations, your specific assemblies might be different.  So just replace them above accordingly… you are all devs after all ;)

Of course, to fix, simply re-apply the patch above.

This problem is still present as of Windows 10 Insider Preview Build 14257.rs1_release.160131-1800

Advertisements

ASP.NET MVC always throws a System.Globalization.CultureNotFoundException


I ran into this problem today.

Being an overly pedantic developer, I was annoyed that my ASP.NET MVC project was always silently throwing this exception on startup.  So I dug into the guts of System.Web.dll to find out ‘why’ this exception was being thrown.

It turns out that upon startup, ASP.NET tries to create the CultureInfo for the project by looking for the good old Satellite directories… so far, so good, this makes total sense.

The issue is more about HOW this is done.

The System.Web.Compilation.StandardDiskBuildResultCache class calls its internal FindSatelliteDirectories method.

This, in turn, fetches all the folders (a.k.a. Directories) that it finds in the Temporary ASP.NET files temp folder, and iterates over them to see if any of them are Satellite Directories.

There is a conditional statement to bypass this check if the folder is called ‘assembly’ or ‘hash’, yet it fails to check if the folder is called ‘UserCache’, which also definitely not a satellite folder.

Personally I think this is bad design in the first place, since:

  1. Satellite folders have a predictable naming convention
  2. Why check for what it is not rather than what it is?
  3. What happens if the developer decides to throw in another 5 folders? This would be an extra 5 exceptions being thrown… and nobody likes the computational cost of exceptions.

I really wish Microsoft would fix this… until then, we’re going to have to live with seeing a bunch of ‘System.Globalization.CultureNotFoundException’ on startup :(

Note: the System.Web.dll that I am checking is v4, and the one that comes with .NET Framework v4.5

 

Setting CSharp (C# / CSC.exe) Compiler Defaults


A little known secret about the .NET C# Compiler (CSC.exe) is that it allows us to set ‘global defaults’.

To do this, create a text file called CSC.rsp in one of two places:

  • The current directory (handy for project specific settings)
  • The directory where CSC.exe is stored
    (generally found in C:\Windows\Microsoft.NET\Framework\{version}\csc.exe)

Note that local settings (current directory) will override the global settings.  Also note that there already exists a global CSC.rsp file with the common ‘includes’, you can either add to this, or simply add a setting to this global file that also includes a secondary settings file (more below).

Any command-line switches that you would normally pass to csc.exe can be added in this text file.

If you do not want these settings to be global, but you want to still supply settings in a text file (handy for multi-project settings which you only want to update in one place), just add them to a different named text file and add a command-line argument to csc.exe like so:

csc.exe @{path\to\settings\file.txt} …

If on the other hand you want to explicitly ignore any local or global settings file, simply run csc.exe using the /noconfig argument.

Making visual studio extensions work with vs 2011 developer preview


If you want to make your Visual Studio 2010 extensions work in Visual Studio 2011 Developer Preview, there is a little hack that you can do.

NOTE: Since this is a hack, there is NO guarantee that the extension will work properly.  But it might be worth giving a shot if, like me, the only thing stopping you from using VS 2011 is a few extensions that you just cannot live without :)

Also note that this only applies to vsix extensions.

1. Download the vsix file

To do this, go to the Visual Studio Gallery and search for your extension of choice.

Visual Studio Gallery
Visual Studio Gallery

Once you find you extension, download it to your desktop (or wherever)

Download Visual Studio Extension
Download Visual Studio Extension

(yes, that is one extension that I just cannot live without, it’s fantastic! Get it here)

2. Rename the file to zip

Once the file is downloaded, simply append .zip to the file name.

vsix renamed to zipAnd expand it into a folder using the default Windows ‘Extract All…’ option (right-click context menu) or whatever tool you want.

3.Edit the manifest

Next, in the expanded folder, edit the file extension.manifest using notepad, wordpad or whatever (I use Notepad++).

Look for the text ‘<VisualStudio Version‘, and change the value to read "11.0"

Change Visual Studio Version For ExtensionSave and close :)

4. Compress the folder content

Now, compress the folder content back into a zip file, using whatever tool you want.

In Windows, you can select all the content in the folder (CTRL+A), right-click, and select ‘send to’ and ‘compressed (zipped) folder’

Compress a folder to zip5. Rename the file back to vsix

Once compressed, rename the file back to .vsix

VSIX Visual Studio Extension6. Install it

Now all you need to do to install it is to Double-Click it.

Good luck :) It might not work, or it might partially work… but this system should allow you to install it.

Hope it helps :)  If anyone has any great extension suggestions, please let me know.

Extending LINQ to allow foreach constructs


Whilst playing around with LINQ over enumerations, I have asked myself whether or not one can extend normal LINQ functionality to also allow a foreach-like construct to form part of the expression itself (very similar to what you would do in jQuery).

Now LINQ results are in the form of IEnumerable instances, and IEnumerable does not supply a ForEach method, yet .NET 3.5 has also given us extension methods… so all we need to do really is to define an extension method like so:

private static void ForEach<T>(this IEnumerable<T> result, Action<T> action){
foreach (T entry in result) action(entry);
}

This will allow us to execute queries of this form:

(from x in [some array] where [some condition involving x]).ForEach([do something with x]);

Not exactly as elegant as fully compliant LINQ syntax, but way better than the alternatives :)

WPF Localised Bindings – What to do when they just don’t seem to work :)


I am currently working on a system in Arabic (no, I don’t understand Arabic), and I bumped into an issue where Bindings were not respecting my CurrentUICulture.

Digging bit deeper (with the help of a handy decompilation tool) I found a not-so-beautiful line in FrameworkElement.cs

public static readonly DependencyProperty LanguageProperty =
DependencyProperty.RegisterAttached("Language", typeof(XmlLanguage),
_typeofThis, new FrameworkPropertyMetadata(XmlLanguage.GetLanguage("en-US"),
FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsMeasure));

As you can see, WPF does NOT respect your thread’s CurrentUICulture.

The fix is simple… finding it, on the other hand, was a nightmare.

Just override the metadata as follows:

FrameworkElement.LanguageProperty.OverrideMetadata
(typeof (FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

Hope it helps :)