.net 为什么控制台构建生成的project.assets.json与使用VS IDE构建生成的project.assets.json完全不同?
我们有大约100个项目的大解决方案,这些项目依赖于许多NuGet软件包,其中一些是内部开发的。这个问题是关于主web应用程序的,它是这个解决方案的中心.net 为什么控制台构建生成的project.assets.json与使用VS IDE构建生成的project.assets.json完全不同?,.net,visual-studio,msbuild,nuget,devenv,.net,Visual Studio,Msbuild,Nuget,Devenv,我们有大约100个项目的大解决方案,这些项目依赖于许多NuGet软件包,其中一些是内部开发的。这个问题是关于主web应用程序的,它是这个解决方案的中心 我们想考虑迁移到新的SDK风格的项目(我们可以),第一步是将所有的项目迁移到打包访问。当代码构建时,出现了一个大麻烦 在带有msbuild的控制台上,我们在bin文件夹中获得System.Buffersversion 4.0.3.0 在带有devenv/build的控制台上,我们在bin文件夹中获得System.Buffersversion 4
我们想考虑迁移到新的SDK风格的项目(我们可以),第一步是将所有的项目迁移到打包访问。当代码构建时,出现了一个大麻烦
- 在带有
的控制台上,我们在bin文件夹中获得msbuild
version 4.0.3.0System.Buffers
- 在带有
的控制台上,我们在bin文件夹中获得devenv/build
version 4.0.3.0System.Buffers
- 在VSIDE(我使用16.7.7)中,我们在bin文件夹中获得
version 4.0.2.0(!!!)System.Buffers
- 没有项目显式引用System.Buffers
- 我们有一个适当的流程,确保所有项目都引用特定NuGet包的完全相同版本。未能遵守规则将导致PR构建失败。但是,它对这些NuGet包的可传递依赖项没有帮助。因此,我们不得不处理程序集绑定重定向(即使我们所有的项目都没有签名,也没关系,许多依赖项都有签名)
- 两个版本之间没有代码更改,仅删除了相应Web应用程序的bin文件夹
devenv/build
生成与msbuild
完全相同的project.assets.json文件这一事实所震惊
我的理论——它与VS采用的快速最新启发式有关,但我不想禁用它——它可以节省大量时间。这只是一个理论,一个薄弱的理论,因为毕竟代码没有改变
我的方法是运行以下脚本:
$FileItem = Get-Item .\bin\_PublishedWebsites\MyWebApp\bin\System.Buffers.dll
del $FileItem.Directory.FullName -r -Force
r.ps1 -NoPull -Main -NoValidateSolutions
[reflection.assemblyname]::GetAssemblyName($FileItem.FullName)
Copy-Item .\UI\MyWORKBits\obj\project.assets.json c:\temp\_msbuild.project.assets.json
del $FileItem.Directory.FullName -r -Force
devenv Main.sln /build
[reflection.assemblyname]::GetAssemblyName($FileItem.FullName)
Copy-Item .\UI\MyWORKBits\obj\project.assets.json c:\temp\_devenv.project.assets.json
del $FileItem.Directory.FullName -r -Force
$VSInstanceFinder = (Get-ToolFromNuGet VSInstanceFinder 1.0.20009.1).FullName
Add-Type -Path $VSInstanceFinder
$dte = [VSInstanceFinder2.Program]::Find((Get-Item .\Main.sln).FullName)
$dte.Solution.SolutionBuild.Build()
while (!(Test-Path $FileItem.FullName))
{
Write-Host -NoNewline '.'
Start-Sleep 10
}
[reflection.assemblyname]::GetAssemblyName($FileItem.FullName)
Copy-Item .\UI\MyWORKBits\obj\project.assets.json c:\temp\_ide.project.assets.json
bc c:\temp\_console.project.assets.json c:\temp\_devenv.project.assets.json
bc c:\temp\_console.project.assets.json c:\temp\_ide.project.assets.json
最小复制
我仍在制作一个最小的复制品,以展示整个问题。然而,为了证明project.assets.json是不同的(尽管是以一种天真的方式),一个小项目就足够了
Common.csproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{04455D86-A7A4-41E5-B3ED-B0BC65EAFDFD}</ProjectGuid>
<OutputType>Library</OutputType>
<AssemblyName>xyz.Common</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>Bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>Bin\Release\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Dummy.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Antlr">
<Version>3.5.0.2</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
让我们在VS IDE中构建它,并检查project.assets.json文件:
C:\work\vsbug [master]> dir .\obj\project.assets.json | sls projectName
obj\project.assets.json:76: "projectName": "Common",
C:\work\vsbug [master]>
因此,项目名称报告为通用。现在让我们在控制台上构建:
C:\work\vsbug [master]> msbuild /restore .\Common.csproj /v:q
Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
C:\work\vsbug [master]> dir .\obj\project.assets.json | sls projectName
obj\project.assets.json:76: "projectName": "xyz.Common",
C:\work\vsbug [master]>
这一次,项目名称是xyz.Common
就我而言,这是一个良性的区别。但它一开始就不应该存在,而且可能是我们在大解决方案中遇到的问题的症状
请注意,使用SDK样式的项目可以消除这种差异,但我不能在我们的大型解决方案中使用它
devenv/safemode
似乎根本无法恢复任何NuGet包,因此代码无法编译,我无法确定如何使其工作。现在完全没用了
我将尝试用不同的包集生成一个最小的复制,但我已经有一个问题-为什么项目名称不同
编辑1
有一个建议是从预生成步骤运行msbuild.exe-t:restore
。由于我的解决方案有127个C#项目(加上一个公用事业项目),因此修改每个项目是不合理的。相反,我将以下目标添加到目录.Build.targets
:
<Project>
<Target Name="MSBuildRestore" BeforeTargets="BeforeBuild" Condition="'$(BuildingInsideVisualStudio)' == True">
<Exec Command=""$(MSBuildBinPath)\msbuild.exe" /t:Restore /v:q /nologo /m $(MSBuildProjectFullPath)" />
</Target>
</Project>
我仍然需要评估此更改对构建的影响。毕竟,这个命令会递归到它所依赖的每个项目。每一个项目都会称之为
幸运的是,它似乎没有打破VisualStudio的快速更新启发,所以我将使用它运行一段时间,看看它是否没有意外的惊喜
编辑2
不幸的是,从预构建步骤生成project.assets.json并不是一个解决方案。显然,此文件用作构建的输入。以下简单场景显示了该行为:
disablefastupdatecheck=true
以禁用快速更新启发式project.assets.json
文件是在每次构建之前重新生成的
不好。研究 这似乎是VS IDE restore和msbuild restore之间的一个问题,我在许多项目和PC中也遇到了这个问题。因此,到目前为止,这是一个相当大的问题,感谢您指出这个问题 ================================ VS IDE还原上的
projects.assert.json
:
================================
msbuild还原时的projects.assert.json
:
我已经报告了,如果我没有详细描述该问题,您可以对其进行投票并添加任何评论,这样它将得到微软更多的关注。我希望团队能给你一个满意的答复
建议
由于该过程可能需要一段时间,作为消除差异的建议,您可以尝试以下功能:
您只需在VS IDE中的项目预构建事件上添加命令行即可:
msbuild $(MSBuildProjectFullPath) -t:restore
1)右键单击项目属性-->生成事件msbuild $(MSBuildProjectFullPath) -t:restore