关于 Azure Function 找不到 dll 程序集 的问题
关于Azure Function找不到dll程序集的问题
大致现象
静态编译没问题,运行报错内容如下:
Could not load file or assembly 'Microsoft.xxxx.xxxx.xxxx, Version=6.15.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.
或:
无法加载文件或程序集 'Microsoft.xxxx.xxxx.xxxx, Version=6.15.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'。系统找不到指定的文件。
查找问题原因
排除法
依赖冲突?环境冲突?版本问题?不如先找dll消失的原因。
收先尝试将所需的dll放入对应的目录中,
然后将文件读写权限设置为只读、拒绝写入、拒绝执行等,
然后运行项目发现VS报错定位到了如图所示的地方
(一个叫做Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.targets的文件中),
可以看到里面的代码功能明显具有清理Runtime的作用,
这也就导致了我们的dll实际上在运行前就被清理掉了,
这也就是为什么静态编译不报错而运行过程中报错的原因。

这个文件在哪里被用到的呢?通过ChatGPT的检索,知道.targets是MSBuild编译相关的运行代码,在对项目中的文件进行翻找过程中发现了如下文件:
路径:[.csproj项目所在目录]/obj/[项目名称].csproj.nuget.g.targets
内容:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)netstandard.library\2.0.1\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('$(NuGetPackageRoot)netstandard.library\2.0.1\build\netstandard2.0\NETStandard.Library.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.bcl.timeprovider\8.0.0\buildTransitive\netcoreapp2.0\Microsoft.Bcl.TimeProvider.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.bcl.timeprovider\8.0.0\buildTransitive\netcoreapp2.0\Microsoft.Bcl.TimeProvider.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.azure.webjobs.script.extensionsmetadatagenerator\1.2.2\build\Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.azure.webjobs.script.extensionsmetadatagenerator\1.2.2\build\Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.sdk.functions\3.1.2\build\Microsoft.NET.Sdk.Functions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.sdk.functions\3.1.2\build\Microsoft.NET.Sdk.Functions.targets')" />
</ImportGroup>
</Project>可以从上面的内容中看到Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.targets文件所在路径($(NuGetPackageRoot)变量一般为%USERPROFILE%\.nuget\packages路径)
至此,大致清楚了报错的原因:
似乎 Azure Functions 会进行 DLL 清理以缩小部署规模,因为在部署期间大多数文件已经存在,因此您需要<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>在项目文件中关闭该清理,这将阻止清理运行。还有另一个设置,FunctionsPreservedDependencies旨在允许您选择要保留的 DLL
解决办法
接下来通过检索互联网信息,找到了如下方法:
- 安装依赖
Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator>= 1.2.1 - 在项目
.csproj文件中的PropertyGroup标签中添加<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>标签即可
参考
- Azure 函数无法加载文件或程序集 Microsoft.IdentityModel.Protocols.OpenIdConnect
- _FunctionsSkipCleanOutput 和 FunctionsPreservedDependencies
- 阐明 FunctionsPreservedDependencies 和 FunctionsSkipCleanOutput #77460
- 添加了跳过清理输出程序集到 ExtensionsMetadataGenerator 的方法。 #6849
- Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator 1.2.1
评论已关闭