Кто копирует app.config в app.exe.config?
-
22-08-2019 - |
Вопрос
Я пишу IDE для разработки игр, которая создает и компилирует проекты .NET (над которыми я работаю последние несколько лет), и нахожусь в процессе ее обновления, чтобы генерировать выходные данные не только для Windows/Visual Studio, но и для для Linux/MonoDevelop (поразительно простой процесс для .NET, но все же требующий некоторых настроек).
В рамках этого я счел необходимым начать генерировать файл app.config как часть этого для сопоставления зависимых имен DLL с именами зависимостей Linux с помощью элементов <dllmap>.Я не понимаю, кто несет ответственность за копирование файла app.config с выходным именем app.exe.config.В проекте Visual Studio действие сборки для 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 ведет себя в этом отношении аналогичным образом, потому что я не смог найти там специального действия для файлов конфигурации).Я не знаю, как он вообще выбирает, к каким файлам применяется это секретное действие.
Решение
Компилятор C# вообще не заботится о файле конфигурации.Среды сборки (MSBuild и VS) сами позаботятся о копировании этого файла.
Другие советы
Заказ:
- первый файл app.config с действием «Нет сборки» в каталоге проекта.
- первый файл app.config с действием сборки контента в каталоге проекта.
- первый файл app.config с действием «Нет сборки» в подкаталоге
- первый файл app.config с действием сборки контента в подкаталоге
msbuild/xbuild также позволяет вам переопределить это, установив свойство $(AppConfig).
Я думаю, что за копирование отвечает MSBuild.Если вы покопаетесь в стандартных файлах .target, то, вероятно, найдете соответствующие директивы.VS сам по себе не копирует.
Также обратите внимание, что Visual Studio проверяет файл конфигурации.
Немного более технический ответ — ссылки на ваши проекты. 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's .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, см. в этом ответе: https://stackoverflow.com/a/40293508/492336.
Обработка app.config является специальной, она обрабатывается по имени, процесс сборки выберет файл app.config в следующем порядке:
- Выберите значение $(AppConfig), установленное в основном проекте.
- Выберите @(None) App.Config в той же папке, что и проект.
- Выберите @(Content) App.Config в той же папке, что и проект.
- Выберите @(None) App.Config в любой подпапке проекта.
- Выберите @(Content) App.Config в любой подпапке проекта.