{Solved} Key needs to be greater than 0 – Issue with ilmerge

Hello there and welcome to my blog. In today’s blog I will discuss about the error – “Key needs to be greater than 0” error with ilmerge and how to get around that.

I had a class library project where I was referencing Microsoft Graph SDK packages to interact with SharePoint. And before I deploying the assembly, I needed to merge the dependent assemblies and there were 15 of them.

Whenever we think of merging DLLs in .NET, we use the ilmerge command. But much to my surprise, I started getting the error – “Key needs to be greater than 0“.

I was rather surprised as this command was executing alright until I added a few more nuget packages and tried to merge. A bit of searching and with trial and error, I realized that if you have a high number of assemblies to merge, you get this error.

When I reduced the number of assemblies, it started working fine. But for me, merging those 15 assemblies was necessary.

I finally did it with the wonderful ilRepack tool. You can install it as nuget package reference. I am bit old school. So I went ahead and download the Nuget Package file (.nupkg) from the download link.

Change the extension of the downloaded .nupkg file to .zip. And extract the contents. You will find the ilrepack.exe inside the tools folder.

All you now need is to replace the word ilmerge with the word ilrepack in the command line. And you will find that your assemblies are successfully merged.

The wonderful thing with ilrepack is that the command options are exactly same to ilmerge. So if you have a batch file with ilmerge command, you simply need to replace the ilmerge keyword with ilrepack. And everything should work fine.

Below are the command options. For more details you can visit here.

Syntax: ILRepack.exe [options] /out:<path> <path_to_primary> [<other_assemblies> ...]

 - /help                displays this usage
 - /keyfile:<path>      specifies a keyfile to sign the output assembly
 - /keycontainer:<name> specifies a key container to sign the output assembly (takes precedence over /keyfile)
 - /log:<logfile>       enable logging (to a file, if given) (default is disabled)
 - /ver:M.X.Y.Z         target assembly version
 - /union               merges types with identical names into one
 - /ndebug              disables symbol file generation
 - /copyattrs           copy assembly attributes (by default only the primary assembly attributes are copied)
 - /attr:<path>         take assembly attributes from the given assembly file
 - /allowMultiple       when copyattrs is specified, allows multiple attributes (if type allows)
 - /target:kind         specify target assembly kind (library, exe, winexe supported, default is same as first assembly)
 - /targetplatform:P    specify target platform (v1, v1.1, v2, v4 supported)
 - /xmldocs             merges XML documentation as well
 - /lib:<path>          adds the path to the search directories for referenced assemblies (can be specified multiple times)
 - /internalize[:<excludefile>]  sets all types but the ones from the first assembly 'internal'. <excludefile> contains one regex per
                                 line to compare against FullName of types NOT to internalize.
 - /renameInternalized  rename all internalized types
 - /delaysign           sets the key, but don't sign the assembly
 - /usefullpublickeyforreferences - NOT IMPLEMENTED
 - /align               - NOT IMPLEMENTED
 - /closed              - NOT IMPLEMENTED
 - /allowdup:Type       allows the specified type for being duplicated in input assemblies
 - /allowduplicateresources allows to duplicate resources in output assembly (by default they're ignored)
 - /zeropekind          allows assemblies with Zero PeKind (but obviously only IL will get merged)
 - /wildcards           allows (and resolves) file wildcards (e.g. `*`.dll) in input assemblies
 - /parallel            use as many CPUs as possible to merge the assemblies
 - /pause               pause execution once completed (good for debugging)
 - /repackdrop:AttributeClass allows dropping specific members during merging (#215)
 - /verbose             shows more logs
 - /out:<path>          target assembly path, symbol/config/doc files will be written here as well
 - <path_to_primary>    primary assembly, gives the name, version to the merged one
 - <other_assemblies>   ...

Note: for compatibility purposes, all options can be specified using '/', '-' or '--' prefix.

For similar topics on Microsoft.NET and Power Platform, subscribe to my blog using the Subscribe option on right pane.

Debajit Dutta
Business Solutions MVP