3

We are providing an application as a self-contained dotnet core 3.1 single executable file. The exe is running as a service on various Windows Servers:

  • Server 2012 64 bit
  • Server 2016 64 bit
  • Server 2019 64 bit

After some time of running (a week and above), the service fails to restart because of the missing AppName.deps.json file inside the temporary directory:

System.IO.FileNotFoundException: Could not find file 'C:\Windows\TEMP\.net\AppName\4rpjodow.e1g\AppName.deps.json'.
File name: 'C:\Windows\TEMP\.net\AppName\4rpjodow.e1g\AppName.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)

By checking the directory we could see that there are missing some more .json and also .dll files. I guess that the file system cleanup removes all files that are not in use while the service is running.

Deleting the whole temp directory resolves the problem because the exe will be extracted again on startup. The problem seems to be the fact, that only some files get deleted and the content is not beeing extracted again.

Our preferred solution would be to extract the files to a directory outside the temp dir. Until now we did not found an option that would provide this feature. Also any other ideas to avoid deleting the temp files are welcome. We would like to keep on working with a single executable if possible because this makes shipping the application to our customers much more comfortable.

EDIT: This is the current PropertyGroup for publish from .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>
Sebastian
  • 1,569
  • 1
  • 17
  • 20
  • Open the project csproj file with notepad which will contain the instructions for copying the files. Modify as necessary. – jdweng Jan 06 '20 at 11:15
  • There are no instructions for copying files. I edited the question to add my current publish configuration. – Sebastian Jan 06 '20 at 13:08
  • Normally when you add object to a project you use the menu Add Existing Item. then browse to the location of the object. Most objects like a dll will automatically get copied to the bin folder for the project. Some files do not automatically get copied and you need to Right Click the object in Solution explorer and select the copy option. The VS Project properties also has Reference Paths and Build Events to add additional instructions. – jdweng Jan 06 '20 at 13:18
  • 2
    According to [this](https://github.com/dotnet/designs/blob/master/accepted/single-file/extract.md), the extraction location can be configured, but only through the environment, which you can't set from the service configuration. You could, however, set the service startup command to something like `cmd /c DOTNET_BUNDLE_EXTRACT_BASE_DIR=.. && myservice.exe` (disclaimer: this may not actually play nice with the Service Control Manager). This would also be the place to insert a `rmdir` or similar to ensure that the app is either fully there or fully not there. – Jeroen Mostert Jan 06 '20 at 13:21
  • 1
    Alternatively, if running the service under its own dedicated account is an option (which is recommendable from a security standpoint anyway) you could configure the environment variables in that user's profile (for obvious reasons, setting `DOTNET_BUNDLE_EXTRACT_BASE_DIR` globally is not recommendable). Disclaimer: I don't know if these variables are considered at all when running as a service; I recall certain parts of the user profile are ignored when logging on as a service. – Jeroen Mostert Jan 06 '20 at 13:26
  • Thanks for your response, @JeroenMostert. I missed that repository when looking for a solution. Because we are running the service on our customer's servers, setting a global environment variable is not an option to us. Running under a service account is neither. I think for now we will have to ship our application with all the single files. Regarding to your link it seems that there might be some more configuration options in future. We will see... – Sebastian Jan 07 '20 at 08:38

2 Answers2

0

Currently the best solution appears to be to migrate to .NET Core 5.0 as it should now support running single-file apps without need to extract the bundle at all, see this github issue where the work has been tracked and the related design document. Among other goals it states:

Can run managed components of the app directly from bundle, without need for extraction to disk.

Then later:

In contrast to .NET Core 3.x single-file apps, .NET 5 single-file apps do not always self-extract on startup.

If the app needs to be extracted or not should be controlled by optional settings, i.e.:

IncludeAllContentForSelfExtract - Bundle all published files (except symbol files) into single-file app. This option provides backward compatibility with the .NET Core 3.x version of single-file apps.

Michal Hosala
  • 5,570
  • 1
  • 22
  • 49
0

I figured it out that .net 3.0 has bug and it has been fixed in .net 3.1. After upgrading to latest version it got resolved.

Jeet
  • 1
  • 2
  • As described in question the application was already on .net 3.1. Do you have any Links with further details on that bug? – Sebastian Nov 23 '20 at 13:15