1

I have 3 projects:

  • A_MainProject (startup project)
  • B_IntermediateProject
  • C_SharedClassLibrary

The depencies are:

A depends on B & C

B depends on C

and C depends on System only.

Every Project has it's own namespace.

As long as no ILMerge is installed, everything works fine.

If ILMerge is activated for Project A ("A_MainProject") everything still works fine and one self-contained executable for Project A is generated.

If ILMerge is now also activated for the B_IntermediateProject, I get the following error:

Error   2   The type 'C_SharedClassLibrary.SharedClass' exists in both 'c:\dev\ILMergeError\B_IntermediateProject\bin\Debug\B_IntermediateProject.exe' and 'c:\dev\ILMergeError\C_SharedClassLibrary\bin\Debug\C_SharedClassLibrary.dll'    C:\dev\ILMergeError\A_MainProject\Program.cs    12  A_MainProject

I use "MSBuild ILMerge task" 1.0.3-rc2 with "ILMerge" 2.13.0307 (from mbarnett).

The minimal solution contains 3 Projects with one class each. This version has ILMerge activated on only one project and works:

ILMergeError_stillworking.zip

This version has it also activated on project B and produces the error:

ILMergeError_error.zip

If I merge the two exes and the dll with ILMerge externally (ILMergeGUI) everything works fine.

Thank you in advance for answering, Xan-Kun

Xan-Kun Clark-Davis
  • 2,664
  • 2
  • 27
  • 38
  • sounds like a namespace issue at first glance.. – MethodMan Apr 22 '15 at 19:08
  • Hello and thanks for the answer. This has been lowing my mind for 2 days now. Plese let me explain, I come from a Java background and the concept of packages there seems to be a bit different then namespace. Could you please explain a little more, what you exactly mean? Do all classes have to be in the same namespace? – Xan-Kun Clark-Davis Apr 22 '15 at 19:35
  • No they don't have to be in the same namespace and arguably shouldn't. – doogle Apr 22 '15 at 19:43
  • They don't have to be but if you have a method name by chance that is the same for example some of the Microsoft.Interop for example the word `Application` could cause what is know as Method Collision so you would have to fully qualify the method by it's class name `.` Method name does that make sense or since you have the `AnotherMessageBox` in all 3 you would have to fully qualify it by it's namespace it would be nice to see some code in the .cs header how all 3 are defined – MethodMan Apr 22 '15 at 20:08
  • I am terrible sorry for the late answer and am to prepare a sample solution to demonstrate the problem. I had a ot more insight meanwhile and will also post some information. – Xan-Kun Clark-Davis Apr 23 '15 at 21:55
  • Sadly, this situation expecially arises with Test (MSTest). If I use ILMerge in any of my projects, I have to unload all Testing Projects first. Is that "normal"? – Xan-Kun Clark-Davis Apr 28 '15 at 14:09
  • I think GLuck put is absolutely right, I redesigned the build process and use proper build scripts now. Its still complex but much better than before, where I also had to switch the startup project every time. Now there is one build, and it creates the right executables (all of them). – Xan-Kun Clark-Davis May 27 '15 at 13:49
  • I suggest you take a look at this also [The type exists in both DLLs](https://stackoverflow.com/questions/36805570/the-type-exists-in-both-dlls) – Mohfath Nov 21 '18 at 05:14
  • Thanks! It actually mentions some interesting workarounds, like settings a custom alias. – Xan-Kun Clark-Davis Nov 22 '18 at 17:41

1 Answers1

2

The short answer is that you should only enable ILMerge on A, where it'll merge both A+B+C together.

The reason why you hit this error is that when you enable ILMerge on B, B will be repacked with all C types as well (B' = B+C). Hence when ILMerge triggers on A, it'll merge A+B'+C = A+(B+C)+C

Now 2 scenarios can happen:

  1. B uses C internally, and doesn't (publicly) expose any C type (e.g. as method argument or return value). In this case you can make it work through ILMerge options (/internalize on B and /allowDup on A), though you'll end up with twice every C type in the merged assembly A.

  2. B exposes C types, that are maybe used by A. In this case even if you manage to make the merge work, it'll fail at runtime, because A and B' reference different types (e.g. for a class c, B' references B'.c and A references C.c), And you'll get nasty type cast exceptions, because those are 2 different types (same name, same namespace, but different assemblies).

(They're nasty because they don't indicate the assembly mismatch, and exception only says that "c cannot be cast to c", which can be confusing to many)

Marcos Dimitrio
  • 6,651
  • 5
  • 38
  • 62
Gluck
  • 2,933
  • 16
  • 28
  • Hi! I accepted your answer as it seems the most valid. Although I never really got to the bottom of the problem, your first sentence is surely true and if the need for a second (or more) exe files arises, the whole buld process needs to be well designed anyways so that exactly these situations do not arise. – Xan-Kun Clark-Davis May 27 '15 at 13:46