gluck / il-repack

Open-source alternative to ILMerge
Apache License 2.0
1.16k stars 214 forks source link

Error merging VB app in 2.0.27 #347

Closed pricerc closed 2 months ago

pricerc commented 7 months ago

I'm using 2.0.18 ok, but nuget advised me that there was an update, so I decided to try it.

I run the repack in a post-build CMD file, with this snippet: SET ILMERGE_VERSION=2.0.27 SET ILMERGE_PATH=%USERPROFILE%.nuget\packages\ilrepack\%ILMERGE_VERSION%\tools\

Without doing anything else besides changing the minor version from 18 to 27, I get this error:

Failed to resolve assembly: 'Microsoft.VisualBasic.Core, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

KirillOsenkov commented 7 months ago

can you add a /lib:dir option where dir is the directory containing Microsoft.VisualBasic.Core.dll?

pricerc commented 7 months ago

I can give it a go.

I just have to figure out which of the 78 copies of Microsoft.VisualBasic.Core.DLL on my C: drive is the right one...

pricerc commented 7 months ago

I went with this one: /lib:C:\VisualStudio\2022\Professional\dotnet\net8.0\runtime\shared\Microsoft.NETCore.App\8.0.1

Which got rid of the error during repacking. I'll have to test the resulting assembly later - I need to copy it to a test platform to confirm that it works.

But while going through this exercise, I clicked that I'm still using VS 2017 for this particular library which is a .NET Framework 4.8 assembly, but Microsoft.VisualBasic.Core.DLL is a .NET 8.0 assembly.

So I'm not sure why my library would be interested in it, or why ILRepack would want to look for it.

Looking at the merged DLL using ILSpy, there is no reference to Microsoft.VisualBasic.Core.DLL.

KirillOsenkov commented 7 months ago

Cecil needs that dll to resolve some type references (understand signatures, metadata etc) of the input assemblies, even if the actual dll is not used.

KirillOsenkov commented 7 months ago

I’m guessing 2.0.18 was accidentally picking it up from some random location like the GAC or something. We did change the resolve algorithm to rely on the /lib: arguments to make it explicit which ones you need exactly, because people have been picking up wrong dlls from wrong locations accidentally.

pricerc commented 7 months ago

I’m guessing 2.0.18 was accidentally picking it up from some random location like the GAC or something. We did change the resolve algorithm to rely on the /lib: arguments to make it explicit which ones you need exactly, because people have been picking up wrong dlls from wrong locations accidentally.

I still don't understand why it needs the location of a library that none of my assemblies are using, and that is for a different generation of framework.

I've changed it to /lib:"%ProgramFiles(x86)%\dotnet\shared\Microsoft.NETCore.App\6.0.26", which is at least not as hard-coded, and in a "well-known" folder.

KirillOsenkov commented 7 months ago

You can install dotnet tool install -g refdump and then in the directory with all your assemblies, run refdump *.dll -s -a:Microsoft.VisualBasic.Core -t and it will show you which of the assemblies are referencing Microsoft.VisualBasic.Core.dll and why.

pricerc commented 7 months ago

image

pricerc commented 7 months ago

And if I do refdump *.dll -s -t | findstr /i /r Microsoft.*Core then all I get is WebView2.Core

and .Basic.:

C:\Projects\CBS\CBS-Vault\CBS.Vault\bin\Debug>refdump *.dll -s -t | findstr /i /r .*Basic.*
Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a:
    Microsoft.VisualBasic.ApplicationServices.ApplicationBase
    Microsoft.VisualBasic.ApplicationServices.AssemblyInfo
    Microsoft.VisualBasic.ApplicationServices.User
    Microsoft.VisualBasic.CompareMethod
    Microsoft.VisualBasic.CompilerServices.Conversions
    Microsoft.VisualBasic.CompilerServices.DesignerGeneratedAttribute
    Microsoft.VisualBasic.CompilerServices.LikeOperator
    Microsoft.VisualBasic.CompilerServices.NewLateBinding
    Microsoft.VisualBasic.CompilerServices.Operators
    Microsoft.VisualBasic.CompilerServices.ProjectData
    Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute
    Microsoft.VisualBasic.CompilerServices.Utils
    Microsoft.VisualBasic.Conversion
    Microsoft.VisualBasic.DateAndTime
    Microsoft.VisualBasic.DateInterval
    Microsoft.VisualBasic.Devices.Computer
    Microsoft.VisualBasic.Devices.ComputerInfo
    Microsoft.VisualBasic.Devices.Keyboard
    Microsoft.VisualBasic.Devices.ServerComputer
    Microsoft.VisualBasic.FileIO.DeleteDirectoryOption
    Microsoft.VisualBasic.FirstDayOfWeek
    Microsoft.VisualBasic.FirstWeekOfYear
    Microsoft.VisualBasic.HideModuleNameAttribute
    Microsoft.VisualBasic.Interaction
    Microsoft.VisualBasic.MyGroupCollectionAttribute
    Microsoft.VisualBasic.MyServices.ClipboardProxy
    Microsoft.VisualBasic.MyServices.FileSystemProxy
    Microsoft.VisualBasic.MyServices.Internal.ContextValue`1
    Microsoft.VisualBasic.MyServices.RegistryProxy
    Microsoft.VisualBasic.MyServices.SpecialDirectoriesProxy
    Microsoft.VisualBasic.Strings
Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a:
    Microsoft.VisualBasic.Devices.ComputerInfo
    System.ServiceModel.BasicHttpBinding
    System.ServiceModel.BasicHttpSecurityMode
    DevExpress.Data.Filtering.Helpers.CriteriaToBasicStyleParameterlessProcessor
    System.ServiceModel.BasicHttpBinding
    System.ServiceModel.BasicHttpSecurity
    System.ServiceModel.BasicHttpSecurityMode
    DevExpress.Data.Filtering.Helpers.CriteriaToBasicStyleParameterlessProcessor
    System.ServiceModel.BasicHttpBinding
    System.ServiceModel.BasicHttpSecurity
    System.ServiceModel.BasicHttpSecurityMode
    DevExpress.Diagram.Core.BasicShapes
Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a:
    Microsoft.VisualBasic.ApplicationServices.ApplicationBase
    Microsoft.VisualBasic.ApplicationServices.AssemblyInfo
    Microsoft.VisualBasic.ApplicationServices.User
    Microsoft.VisualBasic.CompareMethod
    Microsoft.VisualBasic.CompilerServices.Conversions
    Microsoft.VisualBasic.CompilerServices.DesignerGeneratedAttribute
    Microsoft.VisualBasic.CompilerServices.LikeOperator
    Microsoft.VisualBasic.CompilerServices.NewLateBinding
    Microsoft.VisualBasic.CompilerServices.Operators
    Microsoft.VisualBasic.CompilerServices.ProjectData
    Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute
    Microsoft.VisualBasic.CompilerServices.Utils
    Microsoft.VisualBasic.Conversion
    Microsoft.VisualBasic.DateAndTime
    Microsoft.VisualBasic.DateInterval
    Microsoft.VisualBasic.Devices.Computer
    Microsoft.VisualBasic.Devices.ComputerInfo
    Microsoft.VisualBasic.Devices.Keyboard
    Microsoft.VisualBasic.Devices.ServerComputer
    Microsoft.VisualBasic.FileIO.DeleteDirectoryOption
    Microsoft.VisualBasic.FirstDayOfWeek
    Microsoft.VisualBasic.FirstWeekOfYear
    Microsoft.VisualBasic.HideModuleNameAttribute
    Microsoft.VisualBasic.Interaction
    Microsoft.VisualBasic.MyGroupCollectionAttribute
    Microsoft.VisualBasic.MyServices.ClipboardProxy
    Microsoft.VisualBasic.MyServices.FileSystemProxy
    Microsoft.VisualBasic.MyServices.Internal.ContextValue`1
    Microsoft.VisualBasic.MyServices.RegistryProxy
    Microsoft.VisualBasic.MyServices.SpecialDirectoriesProxy
    Microsoft.VisualBasic.Strings

C:\Projects\CBS\CBS-Vault\CBS.Vault\bin\Debug>
deniszykov commented 7 months ago

Because this is a fairly common "issue" for which we cannot do anything on development side. My suggestion is to catch the Mono.Cecil.AssemblyResolutionException by wrapping its message in something like “[ILREPACK-001] Failed to resolve assembly” and throwing it again. Here, rename one of the related issues with /lib: suggestion to this error message. This will make searching and self-diagnosis of such errors easier. People will find this problem by the error ID and help themselves.

KirillOsenkov commented 7 months ago

If you want to figure out why MS.VB.Core is needed, you need to debug, break in the debugger when it happens and examine the callstack. It will tell you what Cecil was looking at that required that dll.

pricerc commented 7 months ago

So its failing when trying to resolve Microsoft.VisualBasic.MyGroupCollectionAttribute, which in .NET 'core' lives in Microsoft.VisualBasic.Core, but in .NET 'Framework' lives in Microsoft.VisualBasic.

Putting a break point in ReferenceFixator.FixReferences, I can see that the scope at this point is "{Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}"

It is still correct in Cecil.MetadataResolver public virtual TypeDefinition Resolve (TypeReference type).

Then, in TryResolve, it gets broken, after this, the version number has changed to 0.0.0.0:

        private AssemblyDefinition TryResolve(AssemblyNameReference name, ReaderParameters parameters)
        {
            if (name.Name == "System.Runtime" && name.Version.Major != 0 && systemRuntimeVersion is null)
            {
                systemRuntimeVersion = name.Version;
            }

            // heuristic: assembly more likely to be Core after that version.
            // Try to resolve from Core first to prevent the base resolver
            // from resolving Core assemblies from the GAC
            if (IsFrameworkName(name.Name) && name.Version > netcoreVersionBoundary)
            {
                var fromCore = TryResolveFromCoreFixVersion(name);
                if (fromCore != null)
                {
                    return fromCore;
                }
            }

            var result = base.Resolve(name, parameters);

            return result;
        }

The heuristic is not valid for Microsoft.VisualBasic, since the version number for the .NET Framework version of Microsoft.VisualBasic.dll is 10.0.0.0, and the .NET 8.0 version of Microsoft.VisualBasic.Core 8 is 13.0.x.y...

If I skip that logic and go straight to var result = base.Resolve(name, parameters);, I get the correct resolution.

KirillOsenkov commented 7 months ago

Thanks for investigating! It does seem to be a problem, and a regression too, and my fault on top of it. I’ll take a look.

KirillOsenkov commented 5 months ago

I'm trying to reproduce this and I can't find a good repro. Any chance you would be able to create a minimal project that exhibits this problem? I'm guessing it should be relatively simple now knowing that a VB attribute is involved. Once I have a repro (without your added /lib argument) I'll be able to fix the heuristic in the resolver as well as emit a better error message for this situation.

KirillOsenkov commented 5 months ago

This is what I tried: I created a tiny app that uses Newtonsoft and VB and tried to merge it, and it seems to work fine for me:

image

There must be some step that is relevant and I'm missing it.

Dark-Shadow-EGY commented 3 months ago

This is what I tried: I created a tiny app that uses Newtonsoft and VB and tried to merge it, and it seems to work fine for me:

image

There must be some step that is relevant and I'm missing it.

I had the same problem, so I did the same experiment as you and the problem happened to me as well The solution is very simple: ignore the problem I made a copy of "Microsoft.VisualBasic.Core.dll" and put it in the same folder and from here there is no longer a problem. But ignoring is the solution to the problem. For example, if you make a copy of 'Newtonsoft.Json.dll' and change its name to 'Microsoft.VisualBasic.Core.dll', this will solve the problem as well.

@pricerc Try it and share with us if the solution is to ignore.

KirillOsenkov commented 3 months ago

@Dark-Shadow-EGY You're saying that the problem happened to you. It didn't happen to me. I'd love to be able to reproduce the problem so I can fix it. If I can fix it, there's no need to ignore.

Could you please describe your set up and repro steps exactly? What did you do? Where is Newtonsoft.Json.dll? Where is MS.VB.Core.dll? what is the arguments passed to ILRepack.exe? what is the current directory?

Thanks.

Dark-Shadow-EGY commented 3 months ago

https://github.com/gluck/il-repack/assets/53060916/62fa3955-b3d6-4ed3-a7b5-d7b063791310

KirillOsenkov commented 2 months ago

Thanks all! @pricerc your insight was very helpful, and @Dark-Shadow-EGY with your video I was able to reproduce and fix.

KirillOsenkov commented 2 months ago

Published https://www.nuget.org/packages/ILRepack/2.0.34 https://www.nuget.org/packages/ILRepack.Lib/2.0.34