Кто копирует app.config в app.exe.config?

Я пишу IDE для разработки игр, который создает и компилирует .NET-проекты (с которыми я работал в течение последних нескольких лет), и сейчас я обновляю его, чтобы генерировать выходные данные не только для Windows/Visual Studio, но также и для Linux/MonoDevelop (невероятно простой процесс для .NET, но все еще требующий некоторых настроек).

Как часть этого, я счел необходимым начать генерировать файл app.config как часть этого для сопоставления зависимых имен DLL с именами зависимостей Linux с <dllmap> элементы. Я смущен тем, кто отвечает за копирование файла app.config в выходное имя app.exe.config. В проекте Visual Studio для Action для app.config обычно устанавливается значение "Нет", и его настройки указывают, что он не будет скопирован нигде, но когда Visual Studio компилирует проект, он создает app.exe.config( хотя иногда я обнаружил, что это ненадежно). Когда я использую MSBuild для создания файла решения, сгенерированного IDE (для целей отладки), MSBuild копирует app.config в app.exe.config. Но когда я скомпилирую проект с CSharpCodeProvider.CompileAssemblyFromFile, ему (естественно) не нравится, что файл конфигурации включен в качестве исходного кода ( "app.config(1,1): ошибка CS0116: пространство имен не содержит непосредственно элементы, такие как поля или методы" ), и, конечно, он не копирует его на вывод, если я не включаю его в качестве ввода. Могу ли я просто скопировать приложение app.config в app.exe.config самостоятельно или есть более стандартный способ сделать это?

Затруднительно ли перенести первый файл *.config? В моей среде IDE можно было бы переименовать файл app.config или добавить еще один (как в Visual Studio). Мне кажется странным, что в IDE есть это секретное действие для файлов конфигурации (я думаю, что MonoDevelop ведет себя аналогично в этом отношении, потому что я не мог найти специальное действие для файлов конфигурации там). Я не знаю, как он даже выбирает, в каких файлах применяется это секретное действие.

Ответы

Ответ 1

Компилятор С# вообще не заботится о файле конфигурации. Среда сборки (MSBuild и VS) будет заниматься копированием этого файла.

Ответ 2

Order:

  • первый файл app.config с действием "Нет сборки" в каталоге проекта
  • первый файл app.config с действием сборки контента в каталоге проекта
  • первый файл app.config с действием None build, в подкаталоге
  • первый файл app.config с действием сборки контента в подкаталоге

msbuild/xbuild также позволяет вам переопределить это, установив свойство $(AppConfig).

Ответ 3

Я думаю, что MSBuild несет ответственность за копирование. Если вы будете выкапывать файлы с запасом .target, тогда вы, вероятно, найдете соответствующие директивы. VS сам по себе не копирует.

Ответ 4

Обратите внимание, что Visual Studio выполняет проверку файла конфигурации.

Ответ 5

Несколько более технический ответ - ваш проект ссылается Microsoft.CSharp.targets на этот ключ в файле csproj:

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Этот файл разрешит что-то вроде c:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets, в зависимости от версии фреймворка.

Внутри этого раздела есть этот раздел, который выполняет работу:

  <!--
    ============================================================
                                        _CopyAppConfigFile

    Copy the application config file.
    ============================================================
    -->
  <Target
      Name="_CopyAppConfigFile"
      Condition=" '@(AppConfigWithTargetPath)' != '' "
      Inputs="@(AppConfigWithTargetPath)"
      Outputs="@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')">

    <!--
        Copy the application .config file, if any.
        Not using SkipUnchangedFiles="true" because the application may want to change
        the app.config and not have an incremental build replace it.
        -->
    <Copy
        SourceFiles="@(AppConfigWithTargetPath)"
        DestinationFiles="@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')"
        OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
        Retries="$(CopyRetryCount)"
        RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
        UseHardlinksIfPossible="$(CreateHardLinksForAdditionalFilesIfPossible)"
            >

      <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>

    </Copy>

  </Target>

Файл App.Config представляется как переменная среды (ожидается, что он будет присутствовать, но кто его устанавливает, я не знаю):

<ItemGroup>
  <AppConfigWithTargetPath Include="$(AppConfig)" Condition="'$(AppConfig)'!=''">
    <TargetPath>$(TargetFileName).config</TargetPath>
  </AppConfigWithTargetPath>
</ItemGroup>

Изменить:. Как выбрать app.config, см. этот ответ - fooobar.com/info/361068/....

Обработка app.config является специальной, она обрабатывается по имени, процесс сборки будет выбирать файл app.config в следующем порядке:

  • Выберите значение $(AppConfig), заданное в основном проекте.
  • Выберите @(Нет) App.Config в той же папке, что и проект.
  • Выберите @(Content) App.Config в той же папке, что и проект.
  • Выберите @(Нет) App.Config в любой подпапке в проекте.
  • Выберите @(Content) App.Config в любой подпапке в проекте.