use*_*441 13 msbuild csproj visual-studio visual-studio-code
我一直在寻找正确的方法来确保在构建我的项目时将 appsettings.json 复制到 bin 目录。
本文推荐使用“无更新”
<ItemGroup>
<None Update="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
而这个计算器的答案建议使用“无有”:
<ItemGroup>
<None Include="appsettings.json" CopyToOutputDirectory="Always" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
update和 和有include什么区别?
更新和包含有什么区别?
根据这份文件:
用法:
Include 属性 => 要包含在项目列表中的文件或通配符。
Update 属性 => 使您能够修改使用 glob 包含的文件的元数据。
工作范围:
Include attribute:
1.适用于normal .net framewrok(非sdk格式),.net core and .net standard(sdk格式),也适用于C++项目...
2.在许多VS版本中使用(据我所知,从VS2010到VS2019)
3.Include甚至在Targets中的 ItemGroup 中也有效
Update attribute:
1.适用于.net核心项目
2.在VS2017及以后可用
3.在 Target 内的 ItemGroup 中使用时不支持
测试和结果:
不包含 c.txt 时的第一次测试:
<ItemGroup>
<DoSth Include="a.txt"/>
<DoSth Include="b.txt"/>
<DoSth Update="c.txt" Metadata="test"/>
</ItemGroup>
<Target Name="MyTest" AfterTargets="build">
<Message Text="@(DoSth)" Importance="high"/>
</Target>
<!--The output is a.txt and b.txt, no c.txt.-->
Run Code Online (Sandbox Code Playgroud)
包含 c.txt 时的第二个测试:
<ItemGroup>
<DoSth Include="a.txt"/>
<DoSth Include="b.txt"/>
<DoSth Include="c.txt" Metadata="original"/>
<DoSth Update="c.txt" Metadata="test"/>
</ItemGroup>
<Target Name="MyTest" AfterTargets="build">
<Message Text="@(DoSth)" Importance="high"/> <!--The output files are a.txt,b.txt and c.txt.-->
<Message Text="%(DoSth.Identity)+%(DoSth.Metadata)" Importance="high"/> <!--The output Metadata of c.txt is test instead of original-->
</Target>
Run Code Online (Sandbox Code Playgroud)
所以很明显,Update attribute它仅用于更新一个 Item 的元数据。它没有包含某些文件的功能。并且仅当一个文件包含在一个项目中时才有效。
Update + appsettings.json在.net core控制台和asp.net coreWeb 应用程序中使用时要澄清一些事情:
在 Asp.net 核心 Web 应用程序中:
如果您创建一个新asp.net core web项目,appsettings.json默认情况下xx.csproj您可以在解决方案资源管理器中看到该文件。但是如果您阅读了您在那里找不到定义,则定义未明确显示在xx.csprojsdk 格式中。
在这种情况下,如果我们使用类似 的脚本<None Include="appsettings.json" CopyToOutputDirectory="Always" />,它总是可以将该文件复制到输出。
但是对于 script <None Update="appsettings.json" CopyToOutputDirectory="PreserveNewest" />,它只有<Content xxx="appsettings.json"...>在项目文件中没有类似的语句时才有效。
我建议您通过 VS UI 来执行此操作,而不是手动编辑 xx.csproj。我们可以更改Build Action and Copy To Output设置Property Window:
如果我们将 设置build action为None,并将复制到输出设置Copy if Never为Copy Always,则在 xx.csproj 中我们可以找到:
<ItemGroup>
<Content Remove="appsettings.json" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
所以VS为此使用了None+Include。根据以上所有内容,我建议您在您的项目中使用None+Include而不是None+Update。此外,最推荐的方法是在 VS IDE 中通过 UI 控制复制行为,而不是手动编辑。希望以上所有帮助:)
更新1:
我们可以在项目文件中添加这个脚本来输出csproj中未显示的None Items和Content Items的信息:
<Target Name="TrytoFindDefinitionsNowShown" AfterTargets="build">
<Message Text="None: @(None)" Importance="high"/>
<Message Text="Content: @(Content)" Importance="high"/>
</Target>
Run Code Online (Sandbox Code Playgroud)
更新2:
我只是做了一些测试,发现即使在 VS 中的 .net core 控制台项目中,虽然 csproj 中没有定义,但更新可以工作。奇怪的?
最后我发现这是因为该定义隐藏或未显示在 csproj 文件中,实际上当您在项目中有一个 appsettings.json 文件时,您已经有一个已<None Include="appsettings.json"...定义的(有时是 Content+include,ikt 取决于您添加的方式该文件),虽然这在 csproj 中是无效的,请看我的截图:
这就是为什么 Update 可以用于复制行为,尽管它用于修改元数据。在我们使用 Update 之前,None+Include+Appsettings.json虽然 csproj 中没有显示,但已经存在定义。(sdk 格式)
更新3:
我对 Update1 中的脚本做了一些小改动以显示<None Include="appsettings.json">的元数据。
所以在 .net core 控制台项目中,appsettings.json文件默认是
<None Include="appsettings.json" CopyToOutputDirectory="Never" />
Run Code Online (Sandbox Code Playgroud)
这就是None+Include+Always(Overwrite) 和None+Update+Always or PreserveNewest(Modify the metadata) 都适用于复制行为的原因。它可以描述为什么默认情况下即使 VS 在None+Include某处有隐藏定义,该文件也不会被复制。因为CopyToOutputDirectory默认设置为从不。
| 归档时间: |
|
| 查看次数: |
4140 次 |
| 最近记录: |