2009-03-30 18 views
14

Piszę IDE do tworzenia gier, który tworzy i kompiluje projekty .NET (nad którymi pracuję od kilku ostatnich lat) i jestem w trakcie aktualizacji, aby wygenerować dane wyjściowe nie tylko dla Windows/Visual Studio, ale także dla Linux/MonoDevelop (ekscytująco prosty proces .NET, ale wciąż wymagający pewnych poprawek).Kto kopiuje plik app.config do pliku app.exe.config?

W związku z tym stwierdziłem, że konieczne jest rozpoczęcie generowania pliku app.config w celu odwzorowania zależnych nazw bibliotek DLL na nazwy zależności Linuksa z elementami <dllmap>. Nie wiem, kto jest odpowiedzialny za skopiowanie pliku app.config do pliku wyjściowego app.exe.config. W projekcie Visual Studio Build Action for app.config wydaje się normalnie mieć ustawioną wartość "None", a jego ustawienia wskazują, że nie będzie on kopiowany w dowolnym miejscu, ale gdy Visual Studio skompiluje projekt, generuje app.exe.config (chociaż czasami uważałem to za niewiarygodne). Kiedy używam MSBuild do zbudowania pliku rozwiązania wygenerowanego przez IDE (do celów debugowania), MSBuild kopiuje app.config do app.exe.config. Ale kiedy kompiluję projekt za pomocą CSharpCodeProvider.CompileAssemblyFromFile (oczywiście) nie podoba się plik konfiguracyjny dołączony jako kod źródłowy ("app.config (1,1): error CS0116: Przestrzeń nazw nie zawiera bezpośrednio takich elementów jak pola lub metody ") i oczywiście nie kopiuje go do wyjścia, gdy nie uwzględniam go jako danych wejściowych. Czy moim obowiązkiem jest samodzielne kopiowanie pliku app.config do pliku app.exe.config, czy też istnieje bardziej standardowy sposób robienia tego?

Czy podłączenie pierwszego pliku * .config jest nieogrodzone? W moim IDE można sobie wyobrazić zmianę nazwy pliku app.config lub dodanie innego (tak jak w Visual Studio). Wydaje mi się dziwne, że IDE ma tę tajną akcję dla plików konfiguracyjnych (myślę, że MonoDevelop zachowuje się podobnie pod tym względem, ponieważ nie mogłem znaleźć tam specjalnej akcji dla plików konfiguracyjnych). Nie wiem, jak to się dzieje, do jakich plików dotyczy ta tajna akcja.

+0

Aby wyjaśnić moje pytanie jest, ponieważ używam CSharpCodeProvider do kompilacji kodu (bez uciekania się do polecenia powłoki, takie jak MSBuild do kompilowania projektu), co jest poprawny sposób uzyskać app.exe .config w danych wyjściowych? – BlueMonkMN

+0

Proponuję użyć MSBuild w twoim IDE i utworzyć zadania MSBuild dla dowolnego wygenerowanego przez ciebie specjalnego wyjścia do kompilacji, którego MSBuild nie obsługuje. Umożliwiłoby to MSBuildowi kompilację z Twoimi rozwiązaniami. Dodatkowo ułatwiłoby to integrację twojego produktu z ciągłą integracją, taką jak TeamCity. – grover

+0

MSBuild może już skompilować moje rozwiązania. A kiedy już to zrobi, już poprawnie obsługuje app.config. CSharpCodeProvider wydaje się być bardziej bezpośrednim rozwiązaniem z mniejszym narzutem niż wysyłanie do MSBuild. IDE generuje plik rozwiązania, ale nie używa go podczas kompilacji wewnętrznej. – BlueMonkMN

Odpowiedz

8

Kompilator C# w ogóle nie dba o plik konfiguracyjny. Środowiska budowy (MSBuild i VS) zajmą się samodzielnym kopiowaniem tego pliku.

+0

Moje IDE nie używa MSBuild do kompilacji projektu. Używa CSharpCodeProvider. A co powinienem robić mój IDE? – BlueMonkMN

+0

Powinien skopiować plik konfiguracyjny za pomocą 'File.Copy' po kompilacji. –

+0

Skopiuj pierwszy plik * .config do outputname.exe.config i zignoruj ​​dowolny inny plik * .config (który nie powinien istnieć)? – BlueMonkMN

1

Uważam, że za kopiowanie odpowiada program MSBuild. Jeśli chcesz wykopać pliki .target, to prawdopodobnie znajdziesz odpowiednie dyrektywy. VS sam nie kopiuje.

1

Należy również zauważyć, że Visual Studio sprawdza poprawność pliku konfiguracyjnego.

7

Order:

  1. pierwszy plik app.config z Żaden budowania akcji, w katalogu projektu
  2. pierwszy plik app.config z treścią skargi kompilacji w katalogu projektu
  3. pierwszy app.config Żaden z plików kompilacji działania, w podkatalogu
  4. pierwszy plik app.config z zawartością akcji budowlanej, w podkatalogu

msbuild/xbuild również pozwala ci to zmienić, ustawiając właściwość $ (AppConfig).

+0

Twoja wzmianka o właściwości '$ (AppConfig)' była dla mnie bardzo pomocna. Wydaje mi się, że możesz poprawić tę odpowiedź, dodając trochę więcej informacji o tym, gdzie znalazłeś te informacje. Znalazłem kilka dodatkowych wyjaśnień [tutaj] (https://timvw.be/2008/03/17/easily-switching-between-appconfig-files-with-msbuild/), ale jeśli istnieje oficjalny link, który byłby jeszcze lepszy . Jeśli nie, mile widziany jest tylko wzmianka o pliku 'targets'. – julealgon

0

odpowiedzi nieco bardziej techniczny - projekt odwołuje Microsoft.CSharp.targets pomocą tego klucza w pliku csproj:

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

Plik ten będzie rozwiązać coś jak c:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets, w zależności od wersji ramowej.

Wewnątrz niego masz tę sekcję, która działa:

<!-- 
    ============================================================ 
             _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> 

pliku app.config wydaje się być przekazywane jako zmiennej środowiskowej (oczekuje się, że będzie obecny, ale kto ustawia go, I don „t know):

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

Edit: Na jaki wybrano app.config, zobacz tę odpowiedź - https://stackoverflow.com/a/40293508/492336.

Manipulowanie app.config jest szczególny, jest ona traktowana według nazwy, proces kompilacji będzie wybrać plik app.config w następującej kolejności:

  • wybrać wartość $ (AppConfig), ustanowiony w główny projekt.
  • Wybierz @ (Brak) App.Config w tym samym folderze co projekt.
  • Wybierz @ (Content) App.Config w tym samym folderze co projekt.
  • Wybierz @ (Brak) App.Config w dowolnym podfolderze w projekcie.
  • Wybierz @ (treść) App.Config w dowolnym podfolderze w projekcie.
Powiązane problemy