我们将一个应用程序作为独立的dotnet core 3.1单个可执行文件提供。exe 在各种 Windows 服务器上作为服务运行:
- 服务器 2012 64 位
- 服务器 2016 64 位
- 服务器 2019 64 位
运行一段时间后(一周及以上(,由于临时目录中缺少AppName.deps.json文件,服务无法重新启动:
System.IO.FileNotFoundException: Could not find file 'C:WindowsTEMP.netAppName4rpjodow.e1gAppName.deps.json'.
File name: 'C:WindowsTEMP.netAppName4rpjodow.e1gAppName.deps.json'
at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at System.IO.File.OpenRead(String path)
at Microsoft.Extensions.DependencyModel.FileWrapper.OpenRead(String path)
at Microsoft.Extensions.DependencyModel.DependencyContextLoader.LoadContext(IDependencyContextReader reader, String location)
at Microsoft.Extensions.DependencyModel.DependencyContextLoader.Load(Assembly assembly)
at Microsoft.Extensions.DependencyModel.DependencyContext.Load(Assembly assembly)
at Microsoft.Extensions.DependencyModel.DependencyContext.LoadDefault()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at System.Lazy`1.get_Value()
at Microsoft.Extensions.DependencyModel.DependencyContext.get_Default()
at Serilog.Settings.Configuration.Assemblies.AssemblyFinder.Auto()
at Serilog.ConfigurationLoggerConfigurationExtensions.Configuration(LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, String sectionName, DependencyContext dependencyContext)
at Serilog.ConfigurationLoggerConfigurationExtensions.Configuration(LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, DependencyContext dependencyContext)
at AppName.Program.<>c__DisplayClass2_0.<CreateWebHostBuilder>b__2(WebHostBuilderContext hostingContext, ILoggingBuilder logging)
at Microsoft.AspNetCore.Hosting.WebHostBuilderExtensions.<>c__DisplayClass9_1.<ConfigureLogging>b__1(ILoggingBuilder builder)
at Microsoft.Extensions.DependencyInjection.LoggingServiceCollectionExtensions.AddLogging(IServiceCollection services, Action`1 configure)
at Microsoft.AspNetCore.Hosting.WebHostBuilderExtensions.<>c__DisplayClass9_0.<ConfigureLogging>b__0(WebHostBuilderContext context, IServiceCollection collection)
at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
at AppName.Program.Main(String[] args)
通过检查目录,我们可以看到缺少更多的.json和.dll文件。我猜文件系统清理会删除服务运行时未使用的所有文件。
删除整个临时目录可以解决问题,因为 exe 将在启动时再次提取。问题似乎是这样一个事实,即只有一些文件被删除,并且内容不会再次提取。
我们首选的解决方案是将文件解压缩到临时目录之外的目录中。到目前为止,我们还没有找到可以提供此功能的选项。也欢迎任何其他避免删除临时文件的想法。如果可能的话,我们希望继续使用单个可执行文件,因为这样可以将应用程序交付给我们的客户更加舒适。
编辑:这是从.csproj发布的当前属性组:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<Version>1.0-develop</Version>
<ApplicationVersion>1.0-develop</ApplicationVersion>
<Description>App-Description</Description>
<Copyright>Copyright © 2019 Company</Copyright>
<LangVersion>8</LangVersion>
<PublishTrimmed>true</PublishTrimmed>
<PublishSingleFile>true</PublishSingleFile>
<ApplicationIcon>Icon.ico</ApplicationIcon>
<AssemblyName>AppName</AssemblyName>
<RootNamespace>AppName</RootNamespace>
<PreserveCompilationContext>false</PreserveCompilationContext>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
目前最好的解决方案似乎是迁移到 .NET Core 5.0,因为它现在应该支持运行单文件应用程序,而无需提取捆绑包,请参阅此 github 问题,其中已跟踪工作和相关设计文档。除其他目标外,它指出:
可以直接从捆绑包运行应用的托管组件,而无需提取到磁盘。
然后后来:
与 .NET Core 3.x 单文件应用相比,.NET 5 单文件应用并不总是在启动时自解压。
是否需要提取应用程序应通过可选设置进行控制,即:
包括所有内容用于自我提取- 将所有已发布的文件(符号文件除外(捆绑到单文件应用程序中。此选项提供与 .NET Core 3.x 版本的单文件应用的向后兼容性。
我发现 .net 3.0 有错误,并且已在 .net 3.1 中修复。升级到最新版本后,它得到了解决。