The State of Linkers for .NET apps (aka "Please Sir, May I have a Linker" 2009 edition)

C#.Netvb.netMonoLinker

C# Problem Overview


Many people here are probably familiar with one of Joel Spolsky most popular blog posts, Please Sir, May I Have a Linker, where he cries out for a way to remove dependencies on the .NET framework so a stand-alone application can be developed and sold.

Jason Zander of the Visual Studio development team, at the time, replied with his views on the topic, arguing that the topic is somewhat moot - the ability to fix security problems in the runtime (among other points) was their chief concern. Overall, the small overhead was worth it.

Fast forward to 2009. There's a few groups out there now claiming to have C# linkers. (Jason Zander even said himself that it wouldn't take much to implement one.) Instead of the cute, dozen-so meg download of .NET 1.0, we now have a massive 200-300 mb cross-platform complete .NET 3.5 installer that contains versions of .NET for x86, x64, and ia64. Microsoft's suggestions to decrease the runtime size include:

  • Unpack the redistributable, remove the target platforms you don't want, and put it back together
  • Use the web bootstrapper that only downloads the libraries for your platform
  • Use the Client Profile installer (new as of late 2008) which has limited libraries and only works for x86

To make matters worse, as I understand it (please correct me if I'm wrong) the client profile don't even register with windows as having .NET 3.5 installed. This means if multiple .NET 3.5 client applications are installed on the computer, none will see each other and the runtime will be re-installed again and again!

I really don't know what Microsoft is thinking here. Even assuming the worst case install will be for one target platform (eg, x64) and only those libraries need to be included, you're still looking at upwards of 60 mb overhead on your app. Even one of the most well known .NET apps, Paint.NET, was fraught with Difficulties installing the application because of the massive .NET dependencies. If THEY have problems distributing a free app, what about the rest of the world? In the end, they had to Make a bootstrapper that installed Microsoft Installer 3.1, the .NET runtime bootstrapper, and all their other dependent libraires before they could install their own application.

So how about it. A linker. Do any good ones exist - or a tool that simply makes it possible to build a C# application without requiring that the user install the massive .NET runtime?

Update: so, it looks like there's a couple of options:

Mono:

.NET:

It looks like the Mono tools are getting use; how about the .NET based tools? Any other experience with them, or are we just going to have to wait for Microsoft to push it 3.5 out to everyone? I shudder to think how long it'll take for .NET 4.0 to be put out...

C# Solutions


Solution 1 - C#

The case of the http://mono-project.com/Linker">Mono Linker.

I can't talk much about the other pieces of software that are listed here, but as the author of the Mono Linker, I can tell what it does and what it does not.

The Mono Linker is only a managed linker, so by definition, it takes assemblies, and removes what's not necessary for a program to run. It doesn't merge assemblies all together, and it doesn't make a native program out of them.

There's a Mono.Merge clone of ILMerge, but it's not complete, and its author is not maintaining it. To generate a native program containing both the Mono runtime and assemblies, Mono provides the mkbundle tool.

Also, as it is only a managed tool, which is altering assemblies, if you give it strong named assemblies, and that you don't have the private keys to sign them back, you'll have troubles running those assemblies.

I wrote a couple of blog posts about the linker:

About our experience with the Linker. The Linker is currently used in two parts of the Mono project. It's used to generate the assembly that we distribute for people to embed our C# compiler, Mono.CSharp.dll. You can watch Miguel's presentation at the PDC, which describes how we do that. It's pretty straightforward, and it's a basic usage of the Linker, which is a customizable tool, and it's pretty easy to write custom steps for it.

A more complex use of the Linker is the way we create our Moonlight assemblies. Moonlight being our implementation of Silverlight, the assemblies are a subset of the desktop assemblies. So we link our desktop assemblies to reduce their sizes, and using custom steps, we're transforming the public API to match Silverlight's.

So yeah, the Linker has some pretty rough edges, such as the command line interface for instance, or the fact that you have to really know what you're doing, or you may end up with some weird assemblies, but all in all, it works really well for us.

Solution 2 - C#

FWIW

Mono has had a linker for quite a while.

Here is an example of how to use mkbundle.

Solution 3 - C#

http://www.xenocode.com/

This is what we use. So far, after a year or to of somewhat limited use (maybe 500 installations in the wild), zero problems.

And it's pretty reasonably priced. They have some more expensive full virtualization software (that bundles your app with other apps and even an O/S). But we didn't need all of that. Our cost a year or so ago was $400.I think it's a bit more expensive now but much less than Thinstall.

And they have great demos you can download, like [IE 8. No install required.][2]

[2]: http://www.xenocode.com/start/?a=IE8 "Run IE 8 without installing it"

Solution 4 - C#

Client profile registers with Windows, but in a special way since you don't want to confuse a machine with only client profile with a machine with the full .net 3.5

Client profile:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\DotNetClient\v3.5\Install 

Full .net 3.5:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\Install

Solution 5 - C#

This is the main one I heard of a long time ago on .NET Rocks. I never really got a change to try it out though

http://www.remotesoft.com/linker/

Solution 6 - C#

Never used it, but I've heard you can do similar things with .NET Reactor

Solution 7 - C#

I was arguing ( under my pen name "Mr Analogy") the need for a linker on Joel's forum for a while before he wrote that article. The proliferation of linkers seems to have justified my concern (sadly).

http://www.thinstall.com/

From folks I've talked to, it's fairly well regarded, although last I checked the licensing was onerous ($2k/year per app licensing). They seem to be targeting IT shops rather than sw developer. The fact that you can't find pricing on their site suggests (to me) that it's expensive.

Solution 8 - C#

There is a great article on CodeProject that talks about some of the "linkers" and how they work.

http://www.codeproject.com/KB/dotnet/internals_native.aspx

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobert PView Question on Stackoverflow
Solution 1 - C#Jb EvainView Answer on Stackoverflow
Solution 2 - C#Sam SaffronView Answer on Stackoverflow
Solution 3 - C#Clay NicholsView Answer on Stackoverflow
Solution 4 - C#NirView Answer on Stackoverflow
Solution 5 - C#Jacob AdamsView Answer on Stackoverflow
Solution 6 - C#Lurker IndeedView Answer on Stackoverflow
Solution 7 - C#Clay NicholsView Answer on Stackoverflow
Solution 8 - C#TWAView Answer on Stackoverflow