Вопрос

Я пишу 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) сами позаботятся о копировании этого файла.

Другие советы

Заказ:

  1. первый файл app.config с действием «Нет сборки» в каталоге проекта.
  2. первый файл app.config с действием сборки контента в каталоге проекта.
  3. первый файл app.config с действием «Нет сборки» в подкаталоге
  4. первый файл 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 в любой подпапке проекта.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top