Skip to content

TerraFx.Interop.Windows is not getting trimmed when compiled using NativeAOT #66593

@jkotas

Description

@jkotas

Repro (this is slightly modified repro from #66545):

using System;
using System.Reflection;

using TerraFX.Interop.Windows;
using static TerraFX.Interop.Windows.Windows;
using static TerraFX.Interop.Windows.COINITBASE;
using static TerraFX.Interop.Windows.CLSCTX;
using System.Runtime.InteropServices;

namespace MyApp // Note: actual namespace depends on the project name.
{
    internal unsafe class Program
    {
      
        static void Main(string[] args)
        {
            var a = Assembly.Load("TerraFx.Interop.Windows");
            foreach (var t in a.GetTypes()) Console.WriteLine(t);

            Console.WriteLine(WMI("Win32_Processor", "ProcessorId"));
        }
        public static string WMI(string wmiClass, string wmiProperty)
        {
            var hresult = CoInitializeEx(null, (uint)COINITBASE_MULTITHREADED);
            if (FAILED(hresult))
                return "";
            hresult = CoInitializeSecurity(
        null,
        -1,
        null,
        null,
        0,
        3,
        null,
        0,
        null
    );
            if (FAILED(hresult))
                return "";
            IWbemLocator* pLoc = null;
            hresult = CoCreateInstance(
        __uuidof<WbemLocator>(),
        null,
        (uint)CLSCTX_INPROC_SERVER,
        __uuidof<IWbemLocator>(),
        (void**)(&pLoc)
    );
            if (FAILED(hresult))
                return "";
            IWbemServices* pServ = null;
            hresult = pLoc->ConnectServer(
                    (ushort*)Marshal.StringToBSTR("ROOT\\CIMV2").ToPointer(),
        null,
        null,
        null,
        0,
        null,
        null,
        &pServ
    );
            if (FAILED(hresult))
                return "";
            hresult = CoSetProxyBlanket(
        (IUnknown*)pServ,
        10,
        0,
        null,
        3,
        3,
        null,
        0
    );
            if (FAILED(hresult))
                return "";
            IEnumWbemClassObject* pEnumerator = null;
            hresult = pServ->ExecQuery(
                (ushort*)Marshal.StringToBSTR("WQL").ToPointer(),
                (ushort*)Marshal.StringToBSTR($"SELECT * FROM {wmiClass}").ToPointer(),
                (int)(WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_FORWARD_ONLY | WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY),
                null,
                &pEnumerator
            );
            if (FAILED(hresult))
                return "";
            IWbemClassObject* pclsObj = null;
            uint uReturn = 0;

            string result = "";

            while (pEnumerator != null)
            {
                HRESULT hr =
                    pEnumerator->Next((int)WBEM_TIMEOUT_TYPE.WBEM_INFINITE, 1, &pclsObj, &uReturn);
                if (uReturn == 0)
                    break;
                VARIANT vtProp;

                fixed (char* lpString = wmiProperty)
                    hr = pclsObj->Get((ushort*)lpString, 0, &vtProp, null, null);
                string manufacturer = Marshal.PtrToStringBSTR((IntPtr)vtProp.bstrVal);

                //hr = pclsObj->Get(L"Product", 0, &vtProp, 0, 0);
                //string product = W2A(vtProp.bstrVal);
                //hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
                //string serialNumber = W2A(vtProp.bstrVal);

                result = manufacturer;

                VariantClear(&vtProp);

                pclsObj->Release();
                break;
            }
            pServ->Release();
            pLoc->Release();
            pEnumerator->Release();
            CoUninitialize();
            return result;
        }
    }
}

.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <PublishTrimmed>true</PublishTrimmed>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="TerraFx.Interop.Windows" Version="10.0.20348" />
    <PackageReference Include="Microsoft.DotNet.ILCompiler" Version="7.0.0-*" />
  </ItemGroup>

</Project>
dotnet publish -c Release -r win-x64

Actual result:

The final binary is 36MB. It includes code and metadata for all types in TerraFx.Interop.Windows.

Expected result:

The final binary is <10MB. It only includes code and metadata for types that are actually used by the program.

Publishing with regular IL trimming using IL linker does not have this issue.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions