我们有大约100个项目的大型解决方案,这些项目取决于许多NuGet软件包,其中一些是内部开发的。这个问题是关于作为解决方案中心的主要Web应用程序的。
我们想考虑迁移到新的SDK样式的项目(在可行的情况下),第一步是将所有项目迁移到PackageReference。这是一个大麻烦事-代码建立时
msbuild
的控制台上,我们在bin文件夹中获得System.Buffers
版本4.0.3.0。devenv /build
的控制台上,我们在bin文件夹中获得System.Buffers
版本4.0.3.0。System.Buffers
4.0.2.0版( !!! )。我已经确定差异是由为相关Web应用程序生成的project.assets.json差异引起的。
差异很大,但是绝对的大多数差异是控制台构建的package.assets.json包含的内容比IDE构建的内容多得多。然后是System.Buffers:
注意:
我的问题-有人遇到过吗? 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>
dummy.cs
using Antlr;
让我们在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]>
因此projectName被报告为 Common 。现在,让我们在控制台上构建:
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#项目(加上一个实用程序项目),因此修改每个项目都是不合理的。相反,我将以下目标添加到Directory.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>
我仍然必须评估此更改对构建的影响。毕竟,此命令递归到该项目所依赖的每个项目。每个项目都将调用它。
幸运的是,似乎没有破坏Visual Studio的“快速更新”启发式技术,因此我将对其进行一些研究,看看它是否没有意外的惊喜。
编辑2
不幸的是,从预构建步骤生成project.assets.json并不是解决方案。显然,此文件用作构建的输入。下面的简单场景显示了该行为:
DisableFastUpToDateCheck = true
以禁用“快速更新”启发式检查日志可以发现实际上是在重新编译项目,因为project.assets.json
文件是在每次构建之前重新生成的。
不好。
答案 0 :(得分:0)
研究
这似乎是 VS IDE还原和 msbuild还原之间的问题,我在许多项目和PCS中也遇到了这个问题。所以到目前为止,这是一个相当大的问题,感谢您指出这个问题。
=============================== VS IDE还原上的
projects.assert.json
:
===============================
projects.assert.json
关于msbuild还原:
我已经举报了this issue on our DC Forum,如果我没有详细描述该问题,您可以对其进行投票并添加任何评论,以便它得到 Microsoft 的更多关注。我希望团队能给您满意的答复。
建议
由于,该过程可能需要一段时间,建议以消除差异,因此您可以尝试以下功能:
您只需在 VS IDE 中的项目的预构建事件上添加命令行:
1)右键单击您的项目属性-> 构建事件->在 pre-构建事件命令行:
msbuild $(MSBuildProjectFullPath) -t:restore
2),然后删除bin
和obj
文件夹,在 VS IDE 中重建项目。
前提是您应该将C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe
复制到系统环境变量 PATH
。
如果我的建议不能使您满意,您可以忽略它。