C# 谁将 app.config 复制到 app.exe.config?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/697529/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Who copies app.config to app.exe.config?
提问by BlueMonkMN
I'm writing a game development IDE that creates and compiles .NET projects (which I've been working on for the past few years) and am in the process of updating it to generate output not only for Windows/Visual Studio, but also for Linux/MonoDevelop (a thrillingly simple process for .NET, but still requiring some tweaks).
我正在编写一个游戏开发 IDE 来创建和编译 .NET 项目(我过去几年一直在研究)并且正在更新它以生成不仅适用于 Windows/Visual Studio 的输出,而且用于 Linux/MonoDevelop(一个非常简单的 .NET 过程,但仍需要一些调整)。
As part of this, I have found it necessary to start generating an app.config file as part of this to map dependent DLL names to Linux dependency names with <dllmap> elements. I'm confused about who's responsible for copying the app.config file to the output name app.exe.config. In a Visual Studio project, the Build Action for app.config seems to normally be set to "None" and its settings indicate that it won't be copied anywhere, yet when Visual Studio compiles the project it generates app.exe.config (though I've sometimes found this to be unreliable). When I use MSBuild to build a solution file generated by the IDE (for debugging purposes), MSBuild copies app.config to app.exe.config. But when I compile the project with CSharpCodeProvider.CompileAssemblyFromFile it (naturally) doesn't like the config file being included as source code ("app.config(1,1) : error CS0116: A namespace does not directly contain members such as fields or methods"), and of course it doesn't copy it to the output when I don't include it as an input. Is it my responsibility to simply copy app.config to app.exe.config independently, or is there a more standard way of doing this?
作为其中的一部分,我发现有必要开始生成一个 app.config 文件作为其中的一部分,以使用 <dllmap> 元素将依赖的 DLL 名称映射到 Linux 的依赖名称。我对谁负责将 app.config 文件复制到输出名称 app.exe.config 感到困惑。在 Visual Studio 项目中,app.config 的 Build Action 似乎通常设置为“None”,其设置表明它不会被复制到任何地方,但是当 Visual Studio 编译项目时,它会生成 app.exe.config (虽然我有时发现这不可靠)。当我使用 MSBuild 构建由 IDE 生成的解决方案文件(用于调试目的)时,MSBuild 会将 app.config 复制到 app.exe.config。但是当我用 CSharpCodeProvider.CompileAssemblyFromFile 编译项目时,它(自然地)不会 不喜欢将配置文件作为源代码包含在内(“app.config(1,1) : error CS0116: 命名空间不直接包含字段或方法等成员”),当然它不会将其复制到当我不将其作为输入包含时输出。简单地将 app.config 独立复制到 app.exe.config 是我的责任,还是有更标准的方法来做到这一点?
Is it hardwired to take the first *.config file? In my IDE it's conceivable that the app.config file would be renamed or another one added (just as in Visual Studio). It seems odd to me that the IDE has this secret action for config files (I think MonoDevelop behaves similarly in this regard because I couldn't find a special action for config files there either). I don't know how it even picks to what files this secret action applies.
获取第一个 *.config 文件是否硬连线?在我的 IDE 中,可以想象 app.config 文件将被重命名或添加另一个文件(就像在 Visual Studio 中一样)。我觉得 IDE 对配置文件有这个秘密操作似乎很奇怪(我认为 MonoDevelop 在这方面的行为类似,因为我也找不到配置文件的特殊操作)。我不知道它是如何选择这个秘密操作适用于哪些文件的。
采纳答案by Mehrdad Afshari
The C# compiler does not care about the config file at all. Build environments (MSBuild and VS) will take care of copying that file themselves.
C# 编译器根本不关心配置文件。构建环境(MSBuild 和 VS)将自己负责复制该文件。
回答by XOR
I think MSBuild is responsible for copying. If you would dig trough stock .target files, then you'd probably find corresponding directives. VS by itself doesn't copy.
我认为 MSBuild 负责复制。如果您要挖掘库存 .target 文件,那么您可能会找到相应的指令。VS 本身不会复制。
回答by Rob
Note also that Visual Studio does validate the config file.
另请注意,Visual Studio 会验证配置文件。
回答by radical
Order:
命令:
- first app.config file with None build action, in the project directory
- first app.config file with Content build action, in the project directory
- first app.config file with None build action, in a subdirectory
- first app.config file with Content build action, in a subdirectory
- 项目目录中的第一个具有 None 构建操作的 app.config 文件
- 项目目录中的第一个带有内容构建操作的 app.config 文件
- 子目录中的第一个具有 None 构建操作的 app.config 文件
- 子目录中的第一个带有内容构建操作的 app.config 文件
msbuild/xbuild also allow you to override this by setting the $(AppConfig) property.
msbuild/xbuild 还允许您通过设置 $(AppConfig) 属性来覆盖它。
回答by sashoalm
A slightly more technical answer - your project references Microsoft.CSharp.targets
via this key in the csproj file:
一个稍微技术性的答案 - 您的项目Microsoft.CSharp.targets
通过 csproj 文件中的这个键引用:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
This file would resolve to something like c:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets
, depending on your framework version.
c:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets
根据您的框架版本,此文件将解析为类似的内容。
Inside of it you have this section which does the work:
在它里面你有这个部分来完成工作:
<!--
============================================================
_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>
The App.Config file seems to be passed as an environment variable (it is expected to be present but who sets it, I don't know):
App.Config 文件似乎是作为环境变量传递的(它应该存在但是谁设置的,我不知道):
<ItemGroup>
<AppConfigWithTargetPath Include="$(AppConfig)" Condition="'$(AppConfig)'!=''">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
Edit:For how app.config is selected, see this answer - https://stackoverflow.com/a/40293508/492336.
编辑:有关 app.config 的选择方式,请参阅此答案 - https://stackoverflow.com/a/40293508/492336。
The handling of app.config is special, it is treated By Name, the build process will select the app.config file following this order:
- Choose the value $(AppConfig) set in the main project.
- Choose @(None) App.Config in the same folder as the project.
- Choose @(Content) App.Config in the same folder as the project.
- Choose @(None) App.Config in any subfolder in the project.
- Choose @(Content) App.Config in any subfolder in the project.
app.config 的处理比较特殊,它是按名称处理的,构建过程会按照这个顺序选择 app.config 文件:
- 选择在主项目中设置的值 $(AppConfig)。
- 在与项目相同的文件夹中选择@(None) App.Config。
- 在与项目相同的文件夹中选择@(Content) App.Config。
- 在项目的任何子文件夹中选择 @(None) App.Config。
- 在项目的任何子文件夹中选择 @(Content) App.Config。