Recently I have been coding a C# app using Visual Studio 2017, .NET Framework 4.6.1 and using the WPF form style. It works absolutely fine on Windows 7, 8.1 and 10 as you’d expect since these operating systems fully support .NET Framework 4.6.1, but what about if I want to make my app work on macOS and Linux?

Why you shouldn’t even bother

To cut a long explanation short, Microsoft .NET Framework (any version of it!) is only compatible with Windows, meaning that any app built using it will usually only run on Windows!

If you want to write truly cross-compatible code then don’t rely solely on .NET Framework and instead use something like Xamarin (now part of Visual Studio!) which allows you to write cross-compatible code.

What is Microsoft .NET Framework anyway?

Essentially all Visual C#, C++ and Visual Basic .NET applications made on any version of Visual Studio since Visual Studio .NET (also called ‘Visual Studio 2002’) run on the Microsoft .NET Framework which is a software framework that allows applications written in these languages to interact with the Windows operating system.

The benefit of using the .NET framework is that it works across a variety of Windows versions, starting with 98 and going right up to Windows 10 and controls such as text boxes, labels, check boxes and so on are compatible and displayed on all. Code written for .NET Framework 1.0 on Visual Studio .NET running on Windows 98 is generally still compatible today with Windows 10 because .NET Framework versions are cumulative, meaning that the later versions also include support for the older ones.

And of course the disadvantage is that .NET Framework only works on Windows, so there isn’t a great way to make .NET apps run on other operating systems.

How to run .NET apps on other operating systems

There are ways to emulate .NET Framework and the Windows sub-system on Linux operating systems and macOS using third-party tools which means that some .NET Framework-based apps can run on OSes besides Windows, but there are unfortunately limitations as you will read.

Note in this piece when I say ‘the app’ I am referring to my Storehouse Article Creator that you can read about here.

The first limitation is that WPF apps aren’t compatible with any operating system besides Windows due to the way that WPF apps utilise the .NET Framework and the fact that WPF apps require .NET Framework 3.5 and newer to work. There are several tools out there that can make Windows apps run on a Mac or a Linux-based machine – examples include Wine, Wineskin and Mono. These are all open source and are generally maintained by the communities that wrote them, however none of them have plans to include support for WPF apps in the future. This means that the only version of the app that can run on other operating systems is the Windows Forms version which can run on the older .NET Frameworks that these emulation apps support and has been around for years and years so these tools have been developed to allow these apps to run and have had time to mature. There is a paid emulation tool called ‘Crossover’ that may support WPF apps, but given that it is essentially just a refined version of Wine, I’m not convinced it will.

This does mean that if I want to continue the development of the app for other platforms, I’ll have to continue developing the Windows Forms version of the app. It’s not too much of a deal because the C# code behind the WPF and Windows Forms app is very similar, but it will be more time consuming as time goes on. I actually started developing this project using Windows Forms, but as soon as I wanted to put spell checking into the app and discovered that it’s only possible with WPF apps I switched development to WPF. However, when I discovered that WPF apps can’t run on a Mac, I started developing the Windows Forms version alongside.

macOS and Mac OS X

I used a free program called WineBottler to ‘bottle’ the *.exe file with a load of open-source .NET Framework alternatives (based on a really old version of .NET Framework, mind!) and Windows subsystem emulators into an *.app file that can run on a Mac. WineBottler has an option to ‘bottle itself’ into the *.app file, meaning that the app can run on a Mac that does not have Wine installed – this makes the app accessible to more Mac users and easier to deploy because they don’t also have to download and install Wine.

I don’t own a Mac computer, so instead I run a virtual machine of macOS 10.13 ‘High Sierra’ on my Windows 10 PC inside of VMware Workstation. At the time of writing, High Sierra is the latest version of macOS and it generally works really well in VMware given that it was not designed to run on PC hardware at all. There are some minor bugs, mostly graphics related, and performance issues, but these don’t affect the way that my app seems to run. Using my VM of High Sierra, I used WineBottler to ‘bottle’ the *.exe file and then I transferred the *.app file it created to another VM of High Sierra – only this one didn’t have Wine installed.

 

WineBottler’s app bundle creator options.

The Windows version of the app is under 1MB in size which is absolutely tiny. Unfortunately, because the Mac version has to include .NET Framework and some Windows subsystem files and then a copy of Wine so that the app can run on Macs that don’t have Wine installed, the *.app bundle is usually between 600 and 700MB in size which is considerably larger. It’s not a massive deal but it is of course at least 600 times larger than the Windows version! When zipped using the built-in archiver in High Sierra, the file size is typically halved which makes distribution more manageable.

The results can be seen in the video demonstration of the app running in High Sierra below!

So the usability of the app on a Mac isn’t as good as it is on Windows and what’s interesting is that when the app is run using Wine without bottling it or bundling Wine without the *.app package, it does actually create the ‘export’ folder on the user’s desktop and not inside the *.app package where the *.exe is located. However, this means that the user would need to have Wine installed on their Mac beforehand and would need to know how to run the software in Wine before they could run it.

At the end of the day, although the majority of people who will want to use this program use a Mac, they are generally fairly technically-minded people and I know them all personally. This mean that I could in theory create a VHD (virtual hard disk) of Windows 10, install VirtualBox on their Macs (free!) and then create a virtual machine of Windows 10 for them to use in VirtualBox using that VHD. They could run the Windows version of the app in the virtual machine and that would work so much better for them. You can even set up shared folders between the virtual machine and the host operating system meaning that the exported files could go straight to a folder on their Mac without having to manually copy the files out of the virtual machine. VirtualBox also has the ability to run in ‘seamless mode’ meaning that apps can run without the Windows interface so it looks like they are running on the Mac.

It was really interesting to see the app running on a Mac though!

Using Wine, it was possible to get the Windows Forms version of Article Creator running on macOS 10.13 High Sierra, but it was not as usable as the Windows version.

Linux-based operating systems

I created a virtual machine of Ubuntu 17.10 which is the latest version of Ubuntu at the time of writing and installed Wine and WineTricks (which can be used to resolve some compatibility problems when running .NET apps in Wine) from the Ubuntu Software Store. Unfortunately, it appeared that a Wine extension called ‘wine-mono’ was missing and although I found some instructions on how to install it, it looked complicated and beyond the reach and skill level of the average user. I therefore assumed that providing you could get this app to run on Linux using Wine, it would look and perform similar to how it did on the Mac.

I couldn’t even get the Windows Forms version of my app running under Wine on Ubuntu 17.10 due a missing extension called ‘mono’ which is an open source .NET Framework alternative.

Running the app in a virtual machine of Windows 10 on Linux and macOS

After looking in the virtual machine settings for each of my virtual machines, I found that it was possible to enable VT-X and VT-D hardware virtualisation in VMware virtual machines meaning that it was possible to run a 64-bit virtual machine inside a virtual machine. I first tried installing Windows 10 in a virtual machine inside of VirtualBox on my VMware virtual machine of High Sierra but the performance of VirtualBox on the virtual machine of High Sierra was poor – probably because High Sierra is not designed to run inside of a virtual machine.

I then tried the same on my virtual machine of Ubuntu 17.10 and had much better luck and was able to install a 64-bit version of Windows 10 Pro inside of VirtualBox. I then created a folder on the desktop of the Ubuntu host called ‘VMshare’ and in VirtualBox set this up as a shared folder meaning that the ‘VMshare’ folder is accessible to the host (Ubuntu in this example) and guest (Windows 10) operating systems. This means that the *.exe file for the Article Creator can be placed in the VMshare folder and it will produce the output in the same folder, meaning that the software can be run in the Windows virtual machine and the files it exports are directly accessible on the host operating system so that files don’t need to be manually copied from the virtual machine to the host.

See the video below to see this in action in Ubuntu 17.10.

Also shown in the video is VirtualBox running in ‘seamless mode’ which essentially ‘blends’ the guest operating system into the host. As shown in the video, this makes the app running inside the virtual machine look as if it were really running on Ubuntu!

Article Creator running inside the Windows 10 virtual machine in VirtualBox on Ubuntu 17.10 in ‘seamless mode’. It almost looks like it is running on Ubuntu.

The virtual machine route seems to be a great option for those who want to use the app without having Windows has their main OS. The three disadvantages however are:

  • You must have a copy of Windows to install inside the virtual machine for this to work (a VHD containing the operating system could be circulated but this is potentially not legal)
  • The computer must have a CPU that supports Intel VT-D and VT-X (or AMD equivalent) which means that this idea won’t work on computers with older CPUs
  • The VHD can potentially be gigabytes and gigabytes large (potentially up to size specified when creating the virtual machine!) so there must be available hard drive space

And of course you also must have the virtualisation software installed on your operating system. VirtualBox is free and compatible with macOS, most modern versions of Mac OS X and most popular Linux distributions (such as Ubuntu and Linux Mint), but it might not be compatible with some more obscure operating systems.

Conclusion

It’s funny how the best way to run a .NET app on a Unix-based system such as macOS and Ubuntu is to actually run it in Windows! Funny because it’s true. Wine is really too limiting and buggy to run apps properly, so if you need to write cross-compatible code when relying on Wine to run it for you is not the answer. Instead, check out something like Xamarin instead.