Excel-DNA / ExcelDna

Excel-DNA - Free and easy .NET for Excel. This repository contains the core Excel-DNA library.
https://excel-dna.net
zlib License
1.26k stars 270 forks source link

Question: addin size #657

Closed akasolace closed 6 months ago

akasolace commented 6 months ago

I just upgraded to excel-dna 1.7 and ported my code to .net 6 using Microsoft upgrade tool. I went almost flawless, my addin is now working perfectly but I am surprised that it doubled in size from 4 to 8 MB. I was just wondering if it is normal, i addin are expected to be larger with .net 6 than with framework 4.8 ? If not is there a way to analyse the size of the xll, for example a comparison with the previous one to see what has happened ? Thank you in advance for any suggested help

govert commented 6 months ago

You should have a look at the files in the output directory. Sometimes a NuGet package will bring in a bunch of extra dependencies. You can look at the build output to see what are all the files being packed. If you see anything strange, I'd be happy to have a look.

akasolace commented 6 months ago

Indeed, I see now much more dll in the output directory than I used to have. Also I have to admit I am a bit confused with the proper way to list dependencies.

What I used to do for years, was to list in the dna file all the dll in the output directory <Reference Path="ExcelDna.IntelliSense.dll" Pack="true" />

I had something like 10 entries but now I see something like 30 dlls which are not all listed in the csproj file: <PackageReference Include="ExcelDna.IntelliSense" Version="1.7.0" />

Now, I wonder .... Should all dll by listed in the csproj or only the explicit dependencies ? Does it means my csproj is broken and I should delete and reinstall all nugget packages ? Am I supposed to manually edit the csproj file ?

govert commented 6 months ago

When targeting .NET 6, all the dependencies from your build will automatically be picked up from the .deps.json file, and then packed into the -packed.xll. The .NET build creates the .deps.json file and selects the .dlls to put in the output directory. One thing that's different when building with SDK-style project file and <PackageReference /> references for NuGet, is that you don't need to list the NuGet package dependencies explicitly. For example, the ExcelDna.AddIn package depends on a package called ExcelDna.Integration. But you only need the first one in your project file. Probably nothing is broken, and you just need more libraries to run under .NET 6 than you did under .NET Framework 4.8. But you can explore this by removing stuff from the project files and seeing what happens.

akasolace commented 6 months ago

I tried to remove all nugget and reinstall them all. My csproj is much cleaner but my addin is broken as it seems that dependent project was not packed in the addin. I got the following error when running the packed addin: #EXCEPTION: Could not load file or assembly 'OPL, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. An attempt was made to load a program with an incorrect format.

My addin depend of some nugget and one project which in turn depend of some nugget, like this: image And my addin csproj is like this:

<ItemGroup>
  <ProjectReference Include="..\SabryCode\OPL.csproj" />
</ItemGroup>
<ItemGroup>
  <EmbeddedResource Include="Ribbon\logo.png" />
</ItemGroup>
<ItemGroup>
  <PackageReference Include="ExcelDna.AddIn" Version="1.7.0" />
  <PackageReference Include="ExcelDna.IntelliSense" Version="1.7.0" />
  <PackageReference Include="ExcelDnaDoc" Version="1.7.0" />
  <PackageReference Include="Microsoft.Office.Interop.Excel" Version="15.0.4795.1001" />
  <PackageReference Include="NLog" Version="5.2.7" />
  <PackageReference Include="SC.Memoization" Version="1.1.0" />
  <PackageReference Include="WinForms.DataVisualization" Version="1.9.1" />
</ItemGroup>

Here below an extract of the ouput (I kept only relevant lines):

` 1>------ Rebuild All started: Project: OPL, Configuration: Release Any CPU ------ 1>OPL -> D:\Code\opl\SabryCode\bin\Release\net6.0\OPL.dll 1>Done building project "OPL.csproj".

2>------ Rebuild All started: Project: OPLaddin, Configuration: Release Any CPU ------ 2>OPLaddin -> D:\Code\opl\OPLaddin\bin\Release\net6.0-windows10.0.22621.0\OPLaddin.dll

2>ExcelDnaBuild: -> bin\Release\net6.0-windows10.0.22621.0\OPLaddin-AddIn.dna 2>ExcelDnaBuild: C:\Users\thesa.nuget\packages\exceldna.addin\1.7.0\build..\tools\net6.0-windows7.0\ExcelDna.xll -> bin\Release\net6.0-windows10.0.22621.0\OPLaddin-AddIn.xll

2>ExcelDnaPack: bin\Release\net6.0-windows10.0.22621.0\OPLaddin-AddIn.dna -> bin\Release\net6.0-windows10.0.22621.0\publish\OPLaddin-AddIn-packed.xll 2>PackExcelAddIn: Using base add-in bin\Release\net6.0-windows10.0.22621.0\OPLaddin-AddIn.xll

2>PackExcelAddIn: ~~> ExternalLibrary path OPLaddin.dll resolved to bin\Release\net6.0-windows10.0.22621.0\OPLaddin.dll. 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: OPLADDIN, Length: 43009 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.DOCUMENTATION, Source: Managed deps.json, Length: 3762 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: MEMOIZATION, Source: Managed deps.json, Length: 6076 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTELLISENSE, Source: Managed deps.json, Length: 40106 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: SYSTEM.COLLECTIONS.IMMUTABLE, Source: Managed deps.json, Length: 66439 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: PROTOBUF-NET, Source: Managed deps.json, Length: 133311 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: PROTOBUF-NET.CORE, Source: Managed deps.json, Length: 126548 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: WINRT.RUNTIME, Source: Managed deps.json, Length: 117591 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: NODATIME, Source: Managed deps.json, Length: 156646 2>PackExcelAddIn: -> Updating resource: Type: DNA, Name: MAIN, Length: 567 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: OPL, Source: Managed deps.json, Length: 44953 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: WINFORMS.DATAVISUALIZATION.UTILITIES, Source: Managed deps.json, Length: 79289 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: NLOG, Source: Managed deps.json, Length: 265743 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: WINFORMS.DATAVISUALIZATION, Source: Managed deps.json, Length: 308801 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: MATHNET.NUMERICS, Source: Managed deps.json, Length: 414318 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: MICROSOFT.OFFICE.INTEROP.EXCEL, Source: Managed deps.json, Length: 229816 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: UNITSNET, Source: Managed deps.json, Length: 347268 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: MICROSOFT.WINDOWS.SDK.NET, Source: Managed deps.json, Length: 3459720 2>PackExcelAddIn: Completed Packing bin\Release\net6.0-windows10.0.22621.0\publish\OPLaddin-AddIn-packed.xll. 2>ExcelDnaPack: bin\Release\net6.0-windows10.0.22621.0\OPLaddin-AddIn.xll.config -> bin\Release\net6.0-windows10.0.22621.0\publish\OPLaddin-AddIn-packed.xll.config 2>ExcelDnaPack: bin\Release\net6.0-windows10.0.22621.0\OPLaddin-AddIn64.dna -> bin\Release\net6.0-windows10.0.22621.0\publish\OPLaddin-AddIn64-packed.xll 2>PackExcelAddIn: Using base add-in bin\Release\net6.0-windows10.0.22621.0\OPLaddin-AddIn64.xll 2>PackExcelAddIn: -> Updating resource: Type: CONFIG, Name: MAIN, Length: 701 2>PackExcelAddIn: ~~> ExternalLibrary path OPLaddin.dll resolved to bin\Release\net6.0-windows10.0.22621.0\OPLaddin.dll. 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: OPLADDIN, Length: 43009 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.DOCUMENTATION, Source: Managed deps.json, Length: 3762 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: MEMOIZATION, Source: Managed deps.json, Length: 6076 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTELLISENSE, Source: Managed deps.json, Length: 40106 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: SYSTEM.COLLECTIONS.IMMUTABLE, Source: Managed deps.json, Length: 66439 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: PROTOBUF-NET, Source: Managed deps.json, Length: 133311 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: PROTOBUF-NET.CORE, Source: Managed deps.json, Length: 126548 2>PackExcelAddIn: -> Updating resource: Type: DNA, Name: MAIN, Length: 567 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: WINRT.RUNTIME, Source: Managed deps.json, Length: 117591 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: OPL, Source: Managed deps.json, Length: 44953 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: NODATIME, Source: Managed deps.json, Length: 156646 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: WINFORMS.DATAVISUALIZATION.UTILITIES, Source: Managed deps.json, Length: 79289 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: NLOG, Source: Managed deps.json, Length: 265743 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: WINFORMS.DATAVISUALIZATION, Source: Managed deps.json, Length: 308801 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: MATHNET.NUMERICS, Source: Managed deps.json, Length: 414318 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: MICROSOFT.OFFICE.INTEROP.EXCEL, Source: Managed deps.json, Length: 229816 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: UNITSNET, Source: Managed deps.json, Length: 347268 2>PackExcelAddIn: -> Updating resource: Type: ASSEMBLY_LZMA, Name: MICROSOFT.WINDOWS.SDK.NET, Source: Managed deps.json, Length: 3459720 2>PackExcelAddIn: Completed Packing bin\Release\net6.0-windows10.0.22621.0\publish\OPLaddin-AddIn64-packed.xll. `

Any idea of what is wrong ?

akasolace commented 6 months ago

By curioisty I used the tool exceldna-unpack on my packed dll and I got:

image

So it seems all dlls are present ... The content of the dna file is `<?xml version="1.0"?>

` `
govert commented 6 months ago

The config file is not used under .NET 6.

The error sounds like a 32-bit / 64-bit problem, but all the dependencies look like managed code.

Maybe there is some other native library being loaded that is not being picked up by the packing correctly, or decides how to load 32-bit vs 64-bit in another way. You might need to check whether there are any native dependencies of OPL.dll that are not coming in as NuGet packages. Perhaps compare the output directory of the OPL project with the output of your add-in projects, to look for something missing.

I think you should also replace <PackageReference Include="Microsoft.Office.Interop.Excel" Version="15.0.4795.1001" /> with <PackageReference Include="ExcelDna.Interop " Version="15.0.1" /> (The Excel-DNA package sets up the embedding options correctly.)

akasolace commented 6 months ago

The config file is not used under .NET 6.

Ah ok I was using it to configure Nlog, I will see how this is supposed to be done with .NET 6

I think you should also replace

with

I was using in just one place to apply a csharp code to selected Excel range. I will try to do the same using 'ExcelDna.Interop '

For the time being my packed xll is still broken but one important piece of information is that function nor having arguments are working just fine like e.g. "my_func()" but all functions requiring at least one argument are throwing the error I mentioned above. Maybe that can help finding what is happening

govert commented 6 months ago

Do you mean the not-packed add-in works right? If so, are there any libraries there that are not packed? Is there a subdirectory like 'runtime' under the output?

govert commented 6 months ago

Are you perhaps using the native MKL provider or something similar via MathNet.Numerics ?

akasolace commented 6 months ago

Do you mean the not-packed add-in works right? If so, are there any libraries there that are not packed? Is there a subdirectory like 'runtime' under the output?

correct if I load in Excel the non packed library it works well. also there is a subfolder but it is empty D:\Code\opl\OPLaddin\bin\Release\net6.0-windows10.0.22621.0\runtimes\win\lib\net6.0

akasolace commented 6 months ago

Here below is the full list of dll in the ouput directory, the last one is WinRT.Runtime: ExcelDna.Documentation ExcelDna.IntelliSense MathNet.Numerics Memoization Microsoft.Office.Interop.Excel Microsoft.Windows.SDK.NET NLog NodaTime OPL OPLaddin protobuf-net.Core protobuf-net System.Collections.Immutable UnitsNet WinForms.DataVisualization WinForms.DataVisualization.Utilities WinRT.Runtime

govert commented 6 months ago

I'm a bit surprised seeing the Windows version in the output dir - I normally just see net6.0-windows - not sure it matters.

If you copy all the output files (except .dna and .xll) into the publish directory, does the -packed .xll then work? If so, you can remove files one by one to see when it breaks.

Do you see anything interesting in the Debug output when loading the packed add-in? There are ways we can switch on a bit more logging, by setting environment variables like this:

EXCELDNA_DIAGNOSTICS_DEBUGGER_LEVEL=Verbose
EXCELDNA_DIAGNOSTICS_FILE_LEVEL=Verbose
EXCELDNA_DIAGNOSTICS_FILE_NAME=ExcelDna.log
EXCELDNA_DIAGNOSTICS_LOGDISPLAY_LEVEL=Verbose
EXCELDNA_DIAGNOSTICS_SOURCE_LEVEL=All

Then you get a log file that might be useful.

akasolace commented 6 months ago

If you copy all the output files (except .dna and .xll) do you mean all the dlls or also files like .json, .pdb, .config ... ?

setting environment variables just to be sure, I need to create those environment varaible on my Path ? The log file will then be next to my addin ?

Here below, I put a recap of the various dll and where there are listed ....

output directory decompiled xll in opladdin csproj in opl csproj
ExcelDna.Documentation y y
ExcelDna.IntelliSense y y y
MathNet.Numerics y y y
Memoization y y
Microsoft.Office.Interop.Excel y y y
Microsoft.Windows.SDK.NET y y
NLog y y y
NodaTime y y y
OPL y y
OPLaddin y y
protobuf-net.Core y y
protobuf-net y y y
System.Collections.Immutable y y
UnitsNet y y y
WinForms.DataVisualization y y y
WinForms.DataVisualization.Utilities y y
WinRT.Runtime y y
ExcelDna.Integration y
ExcelDna.Loader y
ExcelDna.ManagedHost y
ExcelDna.Addin y
ExcelDnaDoc y
SC.Memoization y y
OPL.csproj y
govert commented 6 months ago

You can copy everything, if it makes the -packed work, then start removing.

Do you know what requires the WinRT.Runtime ?

akasolace commented 6 months ago

You can copy everything, if it makes the -packed work, then start removing.

I can confirm that copying everything makes the packed xll work. I have to stop now but I will test tomorrow by removing one by one the elements see when it breaks.

Do you know what requires the WinRT.Runtime ?

No

Thank you very much for guiding me !

akasolace commented 6 months ago

So I just made some tests and I realized the issue is not what I thought. Indeed removing all files one by one I realized the packed addin is working just fine. The issue I have is that in my postbuild process I used to rename both the chm and the xll files from "OPLaddin-AddIn64-packed.xll" to simply "OPL.xll". I have been doing that for years and it was working just fine but it seems now, it creates issues. I will try to create the environement variable you suggested to facilitate debugging.

govert commented 6 months ago

You can specify the names of the published addins like this

    <ExcelDnaPackXllSuffix></ExcelDnaPackXllSuffix>
    <ExcelDnaPack32BitXllName>ExcelDna.ImportFunctions32</ExcelDnaPack32BitXllName>
    <ExcelDnaPack64BitXllName>ExcelDna.ImportFunctions64</ExcelDnaPack64BitXllName>
govert commented 6 months ago

Renaming the packed .xll files should not cause any trouble.

akasolace commented 6 months ago

Renaming the packed .xll files should not cause any trouble.

I confirm that for many years it was just fine but since I migrated to .net 6 I can't rename it. I just tried again. Published DLL works fine, I rename it it broke, I put back original name it works fine. Again only function requiring arguments are impacted.

akasolace commented 6 months ago

I have set the environement variables but no log file created ....

akasolace commented 6 months ago

I made some additional test and I realized the issue only appear if I rename the addin as per the dll. If I use any other name it works just fine. It is a very limited restriction so from my point of view I can close this topic. Thank you