.NET Core 3 tek dosya uygulamamı appsettings.json dosyasını bulmak için nasıl edinebilirim?


11

Tek dosya .Net Core 3.0 Web API uygulaması appsettings.json, tek dosya uygulamasının oluşturulduğu aynı dizinde bulunan dosyayı arayacak şekilde nasıl yapılandırılmalıdır ?

Koşu sonrası

dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true

Dizin şöyle görünür:

XX/XX/XXXX  XX:XX PM    <DIR>          .
XX/XX/XXXX  XX:XX PM    <DIR>          ..
XX/XX/XXXX  XX:XX PM               134 appsettings.json
XX/XX/XXXX  XX:XX PM        92,899,983 APPNAME.exe
XX/XX/XXXX  XX:XX PM               541 web.config
               3 File(s)     92,900,658 bytes

Ancak, çalıştırmaya çalışmak APPNAME.exeaşağıdaki hatayla sonuçlanır

An exception occurred, System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\Users\USERNAME\AppData\Local\Temp\.net\APPNAME\kyl3yc02.5zs\appsettings.json'.
   at Microsoft.Extensions.Configuration.FileConfigurationProvider.HandleException(ExceptionDispatchInfo info)
   at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)
   at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load()
   at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
   at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
...

Benzer ancak farklı bir sorunun yanı sıra diğer Stack Overflow sorularının çözümlerini denedim .

Aşağıdakileri geçmeye çalıştım SetBasePath()

  • Directory.GetCurrentDirectory()

  • environment.ContentRootPath

  • Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)

Her biri aynı hataya yol açtı.

Sorunun kökü, PublishSingleFileikili dosyanın sıkıştırılmış ve bir dizinden çalıştırılmasıdır temp.

Bu tek dosya uygulaması durumunda, aradığı konum appsettings.jsonaşağıdaki dizindir:

C:\Users\USERNAME\AppData\Local\Temp\.net\APPNAME\kyl3yc02.5zs

Yukarıdaki yöntemlerin tümü, dosyanın açıldığı yeri gösterir; bu, çalıştırıldığı yerden farklıdır.

Yanıtlar:


14

GitHub'da burada başlıklı bir sorun buldum PublishSingleFile excluding appsettings not working as expected.

Bu, burada başlıklı başka bir konuya işaret ettisingle file publish: AppContext.BaseDirectory doesn't point to apphost directory

İçinde bir çözüm denemekti Process.GetCurrentProcess().MainModule.FileName

Aşağıdaki kod, uygulamayı, ikili dosyaların çıkarıldığı yerden ziyade, tek yürütülebilir uygulamanın çalıştırıldığı dizine bakacak şekilde yapılandırdı.

config.SetBasePath(GetBasePath());
config.AddJsonFile("appsettings.json", false);

GetBasePath()uygulama:

private string GetBasePath()
{
    using var processModule = Process.GetCurrentProcess().MainModule;
    return Path.GetDirectoryName(processModule?.FileName);
}

Bu cevap, artı @ ronald-swaine mükemmel. Appsettings, paketlenmiş exe'den hariç tutulur ve yayınlama görevi, appsettings dosyalarını paketlenmiş exe'nin yanına yerleştirir.
Aaron Hudon

8

Çalışma zamanında yürütülebilir dosyanın dışında kullanılan dosyaları kullanmakta sorun yoksa csproj'da dışarıda istediğiniz dosyaları işaretleyebilirsiniz. Bu yöntem, bilinen bir konumdaki canlı değişikliklere ve benzeri şeylere izin verir.

<ItemGroup>
    <None Include="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      <CopyToPublishDirectory>Always</CopyToPublishDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </None>
    <None Include="appsettings.Development.json;appsettings.QA.json;appsettings.Production.json;">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      <CopyToPublishDirectory>Always</CopyToPublishDirectory>
      <DependentUpon>appsettings.json</DependentUpon>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </None>
  </ItemGroup>

  <ItemGroup>
    <None Include="Views\Test.cshtml">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </None>
  </ItemGroup>

Bu kabul edilemez ve SADECE tek bir dosya olması gerekiyorsa, ana bilgisayar kurulumumdaki kök yol olarak tek dosya ayıklanan yolu iletiyorum. Bu, yapılandırmayı ve (sonradan eklediğim) ustura dosyalarını normal olarak bulmasını sağlar.

// when using single file exe, the hosts config loader defaults to GetCurrentDirectory
            // which is where the exe is, not where the bundle (with appsettings) has been extracted.
            // when running in debug (from output folder) there is effectively no difference
            var realPath = Directory.GetParent(System.Reflection.Assembly.GetExecutingAssembly().Location).FullName;

            var host = Host.CreateDefaultBuilder(args).UseContentRoot(realPath);

Unutmayın, gerçekten tek bir dosya oluşturmak ve PDB yok için aşağıdakilere de ihtiyacınız olacak:

<DebugType>None</DebugType>

Örneğinizdeki Views \ Test.cshtml hedef bilgisayara nasıl ulaşır? Kültüre göre açmam gereken resim ve sözlük dosyalarım var,
Paul Cohen

@PaulCohen Genellikle yayınlanan çıktı konumundan tüm dosyaları SCP kullanarak dağıtırdım. Yalnızca csproj'daki değişikliklerle (ilk örnek), varsayılan kök içerik dizinini kullanan API'lerin dosyalarının çalışma dizininde kullanılabilir olması gerekir. Çıkarılan içeriğin gerçek yolunu elde etmek için 2. örneği kullanmanız gerektiği anlaşılıyor, böylece resimlere tam bir yoldan erişebilir veya içerik kökünün doğru ayarlanmasını sağlayarak ~ / ... yolları görüntüler için jilet kullanılabilir.
Ronald Swaine

Arka planım gömülü uygulamalarda, bu nedenle tek bir ikili genellikle rom'a yazılır. Ne fark ediyorum bir tür kendi kendine ayıklanan "zip gibi" dosyada paylaştığım Exe var. Tüm veri dosyalarım orada ve uygulama çalıştırıldığında her şey doğrudan bir temp'a çıkarılır. Bulursam veri dosyalarımı bulabilirim. Ayrıca bazı başka bir yerde nerede VS hata ayıklamak böylece bazı mantık gerekir anlamına gelir.
Paul Cohen

1
Şu anda bu kurulum var ve rastgele dosyaları bulmak durdu.
Going-gone

1

Uygulamam .NET Core 3.1 üzerindedir, tek bir dosya olarak yayınlanır ve Windows Hizmeti olarak çalışır (bu sorun üzerinde bir etkisi olabilir veya olmayabilir).

Process.GetCurrentProcess().MainModule.FileNameİçerik kökü olarak önerilen çözüm benim için çalışır, ancak yalnızca içerik kökünü doğru yere ayarlarsam:

Bu çalışıyor:

Host.CreateDefaultBuilder(args)
    .UseWindowsService()
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseContentRoot(...);
        webBuilder.UseStartup<Startup>();
    });

Bu çalışmıyor:

Host.CreateDefaultBuilder(args)
    .UseWindowsService()
    .UseContentRoot(...)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup<Startup>();
    });
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.