VB.net on Linux using Wine mixed with Mono C#

So I encountered some legacy VB.net code that I wanted to compile into a cool Nancy-based application that runs under Mono on Linux. After trying to compile my code with an outdated (2008?) Mono VB.net compiler and linking the result with my Mono C# (Nancy) project I got frustrated with the following error:

Mono.CSharp.InternalErrorException: Failed to import assembly `System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
---> System.ArgumentException: Value does not fall within the expected range.
at KVM.Reflection.Fusion.CompareAssemblyIdentityPure

So I tried to compile the VB.net code on Linux, not with Mono, but with the official compiler under Wine. The “winetricks” script makes it actually easy to install “.Net Framework 4”:

sudo apt-get install wine
rm -Rf ~/.wine
WINEARCH=win32 WINEPREFIX=~/.wine winecfg
wget http://winetricks.org/winetricks
chmod +x winetricks
./winetricks dotnet40

We can quickly test the installation with the compile command:

cd /home/maurits/projects/HelloWorld/VisualBasic
WINEDEBUG=-all wine c:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\vbc.exe "/out:VisualBasic.dll" /rootnamespace:VisualBasic /target:library "HelloModule.vb"

Our HelloModule.vb file looks like this:

Imports System

<Assembly: CLSCompliant(True)> 

Public Module HelloModule

	Public Function Hello() as String
		Dim s as String = "Hello World!"
		Return s
	End Function

End Module

Microsoft has a good article on Writing CLS-Compliant Code. These are the rules you have to follow when mixing code from different .net languages. The actual rules are described in a lengthy document titled: Language Independence and Language-Independent Components. Read it or remember this summary from stackoverflow:

  • Unsigned types should not be part of the public interface of the class. What this means is public fields should not have unsigned types like uint or ulong, public methods should not return unsigned types, parameters passed to public function should not have unsigned types. However unsigned types can be part of private members.
  • Unsafe types like pointers should not be used with public members. However they can be used with private members.
  • Class names and member names should not differ only based on their case. For example we cannot have two methods named MyMethod and MYMETHOD.
  • Only properties and methods may be overloaded, Operators should not be overloaded.

Simple right? In C# we will be “using” the VisualBasic DLL (dynamic link library) and it’s HelloModule like this:

using System;
using VisualBasic;

namespace ConsoleApplication1
{
	class ConsoleApplication1
	{
		public static void Main (string[] args)
		{
			Console.WriteLine (HelloModule.Hello());
		}
	}
}

We can actually build our entire solution using “MSBuild.exe” and the following command:

cd /home/maurits/projects/HelloWorld/
WINEDEBUG=-all wine c:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe HelloWorld.sln

Or we can build the individual projects:

WINEDEBUG=-all wine c:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe VisualBasic\\VisualBasic.vbproj
WINEDEBUG=-all wine c:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe ConsoleApplication1\\ConsoleApplication1.csproj

And finally we can also compile the Mono C# project (csproj file) using Mono’s “xbuild” tool:

xbuild ConsoleApplication1/ConsoleApplication1.csproj

If you use “MSBuild.exe” and you the following error when compiling your VB.net code:

vbc : Command line error BC2001: file 'C:\users\maurits\Temp\.NETFramework,Version=v4.0,Profile=Client.AssemblyAttributes.vb' could not be found

Or if you get the following error on your C# code:

CSC : error CS2001: Source file 'C:\users\maurits\Temp\.NETFramework,Version=v4.0,Profile=Client.AssemblyAttributes.cs' could not be found

Then you may want to add the following tag to your “csproj” or “vbproj” project file:

<Target Name="GenerateTargetFrameworkMonikerAttribute" />

You should add it just before the final “</Project>” tag. Why? No clue. Check out stackoverflow yourself, because I simply don’t understand it. You may have to remove the “obj” and “bin” directories before the error disappears.

Note that if you get the following warning (you most probably will):

warning MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.0" were not found.

You get rid of it by installing “Microsoft Windows SDK for Windows 7 and .NET Framework 4” and only install “Intellisense and Reference Assemblies” as explained by Sean Killeen.

Happy coding!

Share

Leave a Reply

Your email address will not be published. Required fields are marked *