我有一个简单的控制台应用程序,它引用一个小型第三方 COM 互操作 .NET 程序集。
我想在发布时修剪未使用的代码。
但是,当我运行修剪后的已发布应用程序时,出现错误:
未处理的异常。 System.IO.FileNotFoundException:文件名: '3rdPartyInteropLibrary,版本=1.3.0.0,文化=中性,PublicKeyToken=null' 在 ClassLibrary1.Class1.Print() 在 Program.Main()
即使我手动将 3rdPartyInteropLibrary.dll 文件复制到输出文件夹,我也会收到错误。
如何配置修剪,以便它只修剪我的代码并保持外部库不变?
--------------------------------- .csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Reference Include="Interop.bpac">
<HintPath>Interop.bpac.DLL</HintPath>
</Reference>
</ItemGroup>
</Project>
public class Program
{
public static void Main()
{
var printer = new bpac.Printer();
var printers = printer.GetInstalledPrinters() as Array;
}
}
我知道 COM 互操作与程序集修剪不兼容,但我希望有一些解决方法,例如修剪除互操作程序集引用的程序集之外的所有内容(例如,保留所有 .NET Standard API 不变)
dotnet/runtime
问题78038“MissingMethodException
在System.Management.WmiNetUtilsHelper
调用期间从wmi
引发(.NET6自包含)”,以及微软文档“已知的修剪不兼容性”,它是显然,修剪和 COM 互操作之间存在固有的不兼容性,这可能会导致像您看到的那样的运行时错误。
核心问题是.NET 修剪功能旨在通过删除被视为“未使用”的代码路径来减小最终发布的应用程序的大小。
但是,此过程依赖于静态分析,无法解释在运行时动态调用的依赖项,这通常是 COM 互操作的情况。
您看到这些是因为修剪器正在删除 COM 互操作所需的代码,并且
BuiltInComInteropSupport
属性在启用时可以禁用某些 COM 互操作功能。 GitHub 问题讨论澄清了 COM 互操作和修剪从根本上不兼容,.NET 团队的建议是在需要 COM 互操作时避免使用修剪。
由于您想要一个解决方案来缩小应用程序大小,同时还使用 COM 互操作,您可能会考虑:
完全避免修剪:这是最安全的方法,并且可以确保存在所有必要的 COM 互操作代码,但它也会导致应用程序大小更大。
手动修剪:使用
DynamicDependency
属性手动注释代码以显式保留所需的依赖关系。这不受支持,并且很容易出错,因为维护是您的责任。
实现与修剪兼容的自定义 com 包装器:这并不简单。
为 .NET 运行时做出贡献,按照 .NET 团队成员的建议,使
System.Management
库修剪兼容。这将是一个有利于整个 .NET 社区的长期解决方案,但超出了单个项目的直接需求范围。
为了立即解决问题,...最好避免修剪。