Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NativeAOT publish fails to statically link WmiLight when it is packaged in a dependent library #14

Closed
danielo-unity3d opened this issue Mar 13, 2024 · 11 comments

Comments

@danielo-unity3d
Copy link

... rather than when used directly in the main program.

Note: I am using dotnet 8.0.202

Actually, the only reason I was eventually able to get a simple WmiLight program to work, was by setting PublishWmiLightStaticallyLinked to true in the main project.

Unfortunately, I don't seem to be able to get this to work when the WMI code is in a dependent library (setting the attribute either in the main project or library project has no discernable impact).

Steps:

dotnet new globaljson --sdk-version 8.0.202 --force
dotnet new console -n Main
dotnet new classlib -n Lib
dotnet add Main reference Lib
dotnet add Lib package WmiLight

We set IsAotCompatible (or just IsTrimmable) in both Main and Lib, but we set PublishAot in the Main project alone (I don't think the latter have any effect if set in the library).
Sadly, setting PublishWmiLightStaticallyLinked in either the Main, the Lib, or both, has no effect.

The code in Lib/ClassLib.cs:

using WmiLight;

namespace Lib;

public class Class1
{
    public static void GetNetworkAddresses()
    {
        using (WmiConnection con = new WmiConnection("root\\StandardCimv2"))
        {
            foreach (WmiObject managementObject in con.CreateQuery("SELECT PermanentAddress FROM MSFT_NetAdapter"))
            {
                var permanentAddress = managementObject["PermanentAddress"] as string;
                if (!string.IsNullOrEmpty(permanentAddress))
                {
                    Console.WriteLine($"  {permanentAddress.ToLower()}");
                }
            }
        }
    }
}

The code in Main/Program.cs:

Lib.Class1.GetNetworkAddresses();

The command to publish:

$ dotnet publish Main

and to run:

$ Main/bin/Release/net8.0/win-x64/publish/Main.exe 
  14cc19d330a0
  025049000021
  18dc18e3301c

But the WmiLight.Native.dll is never substituted for the static library.

$ ll Main/bin/Release/net8.0/win-x64/publish/
total 10656
-rw-r--r-- 1 danielo 197121   11448 Mar 13 09:13 Lib.pdb
-rwxr-xr-x 1 danielo 197121 1860608 Mar 13 09:13 Main.exe*
-rw-r--r-- 1 danielo 197121 8925184 Mar 13 09:13 Main.pdb
-rwxr-xr-x 1 danielo 197121  109056 Dec 11 05:16 WmiLight.Native.dll*

Thanks for your help.

@MartinKuschnik
Copy link
Owner

Hi @danielo-unity3d,

this does not work, because the PublishWmiLightStaticallyLinked option that is introduced by the NuGet package and configures the linker. But this works only on an application not an a library. And because you do not have installed the NuGet package at the main project, ther are no linker properties generated.

It hink you have the following options:

@MartinKuschnik
Copy link
Owner

@danielo-unity3d Do you still need help?

@danielo-unity3d
Copy link
Author

Martin, thanks for taking a look.
It would be nice if the PublishWmiLightStaticallyLinked property (and the WmiLight.prop and WmiLight.target build files that it relies on), could support the WmiLight as a transitive dependency, but if you don't see a easy way to do it, that's OK.
If you ever find out how to do it, let me know.
Thanks.

@danielo-unity3d
Copy link
Author

If the application is trimmed (PublishTrimmed is true), then I get this exception:

Exception has occurred: CLR/System.TypeLoadException
Exception thrown: 'System.TypeLoadException' in WmiLight.dll: 'Could not load type 'System.StubHelpers.ObjectMarshaler' from assembly 'System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.'

@MartinKuschnik
Copy link
Owner

It works in my case. I do not get any exception.

Can you please check my test project and tell me the difference?

test-project.zip

@MartinKuschnik
Copy link
Owner

oh, you mean without NativeAOT?

@MartinKuschnik
Copy link
Owner

We will follow this bug at #15

@MartinKuschnik
Copy link
Owner

@danielo-unity3d Please try to enable the BuiltInComInteropSupport feature. See Trimming during publish for mor details.

Please give me some feedback.

@danielo-unity3d
Copy link
Author

danielo-unity3d commented Mar 17, 2024

Just adding BuiltInComInteropSupport to true, I get:

$ dotnet publish -p:PublishBuildType=Trimmed
...
Optimizing assemblies for size. This process might take a while.
ILLink : Trim analysis error IL2026: Internal.Runtime.InteropServices.ComActivator.GetClassFactoryForTypeInternal(ComActivationContextInternal*)
: Using member 'Internal.Runtime.InteropServices.ComActivator.GetClassFactoryForTypeImpl(ComActivationContextInternal*, Boolean)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Built-in COM support is not trim compatible. https://aka.ms/dotnet-illink/com
C:\Users\user\.nuget\packages\microsoft.net.illink.tasks\8.0.3\build\Microsoft.NET.ILLink.targets(87,5): error NETSDK1144: Optimizing assemblies for size failed. Optimization can be disabled by setting the PublishTrimmed property to false.

Sorry, that's with PublishReadyToRun also set to true...

Now, I'm seeing:

ILLink : Trim analysis error IL2026: Internal.Runtime.InteropServices.ComActivator.GetClassFactoryForTypeInternal(ComActivationContextInternal*)
: Using member 'Internal.Runtime.InteropServices.ComActivator.GetClassFactoryForTypeImpl(ComActivationContextInternal*, Boolean)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Built-in COM support is not trim compatible.

And this is issue #11

If I add the ManagedAssemblyToLink "rule" to the project, to exclude trimming WmiLight, this looks like it is working... but I needed to disable TreatWarningsAsErrors...
There must be a better way to exclude the trimming while also not generating a warning...

@MartinKuschnik
Copy link
Owner

@danielo-unity3d I think i have found a way to fully remove the COM stuff. But I have to be carefull to don't change any return type. Therefore it will take some time.

@MartinKuschnik
Copy link
Owner

@danielo-unity3d Please give Version 6.0.0 a try. This version should work in all deployment cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants