关于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的检索,知道.targetsMSBuild编译相关的运行代码,在对项目中的文件进行翻找过程中发现了如下文件:

路径:[.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, azure function

评论已关闭