Ответ 1
Компилятор С# вообще не заботится о файле конфигурации. Среда сборки (MSBuild и VS) будет заниматься копированием этого файла.
Я пишу 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 ведет себя аналогично в этом отношении, потому что я не мог найти специальное действие для файлов конфигурации там). Я не знаю, как он даже выбирает, в каких файлах применяется это секретное действие.
Компилятор С# вообще не заботится о файле конфигурации. Среда сборки (MSBuild и VS) будет заниматься копированием этого файла.
Order:
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 .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 в любой подпапке в проекте.