Ignore NuGet package restore on .vdproj projects in Azure Pipelines
Asked Answered
D

4

9

I'm attempting to set up an Azure DevOps build pipeline against a .NET Framework 4.7.2 solution which contains a Visual Studio Installer Project. I've set up a self-hosted agent on a Windows Server 2019 VM, which has Visual Studio 2019 Community installed. The build pipeline contains the NuGet Installer task, followed by the NuGet task, set up to restore the referenced NuGet Packages. Below is the YAML snippet:

- task: NuGetCommand@2
  inputs:
    command: 'restore'
    restoreSolution: '$(solution)'

Running a build with this configuration however, results in the following error in the build logs:

[error]The nuget command failed with exit code(1) and error(C:\##############.vdproj(1,1): error MSB4025: The project file could not be loaded. Data at the root level is invalid. Line 1, position 1.)

This appears to be due to a performance enhancement that's been made in newer versions of nuget.exe. The suggestion, based on this GitHub issue, is to enable skipping non-existent package targets using the RestoreUseSkipNonexistentTargets MSBuild setting.

The GitHub issue mentions using the NUGET_RESTORE_MSBUILD_ARGS NuGet CLI environment variable in order to set this property, but I don't know how this can be achieved through the NuGet build task.

Since NuGet is now integrated with MSBuild, I then attempted to set this property to false through a command-line argument on the NuGet task. I modified the YAML, setting the command to custom in order to pass arguments. I based the syntax off of the MSBuild restore documentation. It now looks like follows:

- task: NuGetCommand@2
  inputs:
    command: 'custom'
    arguments: 'restore "$(solution)" -p:RestoreUseSkipNonexistentTargets=false'

This build configuration results in the following error:

[error]The nuget command failed with exit code(1) and error(Unknown option: '-p:RestoreUseSkipNonexistentTargets=false')

My question is, how do I go about getting the NuGet restore task to skip package restore on .vdproj projects?

EDIT

The other project in the solution is a C# WinForms .NET Framework project. We're using packages.config rather than PackageReference.

Deodorize answered 20/12, 2019 at 3:14 Comment(8)
Apart from the installer project, what's the info about other projects? All C#/VB projects? Using PackageReference or Packages.config?Chickabiddy
@LanceLi-MSFT The only other project is a C# WinForms app, using packages.config. Have edited the question for clarity.Deodorize
Hi friend, you need a command like this: nuget restore proj1\packages.config -PackagesDirectory ..\packages . See here.Chickabiddy
Apart from restoring packages for whole solution, you can restore for one separate project. For your situation, this can be more suitable. And for the reason why ` arguments: 'restore "$(solution)" -p:RestoreUseSkipNonexistentTargets=false'` not works, nuget restore command can't recognize the msbuild property.Chickabiddy
Thanks @LanceLi-MSFT, I will try doing that. For this example solution the above should be fine to use, but I wonder when using a solution with dozens of projects, whether the above approach would scale well? Could I perhaps replace the NuGet task with the MSBuild task & do the restore through there? I noticed ADO says this approach is deprecated, but it may be more robust on big solutions or when new projects are added.Deodorize
This workaround for now is only suitable for your current solution. If you have dozens of projects, I would suggest a better way like adding custom msbuild build targets to do that. But it could be more complex though it could work and I'm familiar with msbuild and nuget...Chickabiddy
As for the MSBuild task to do the restore, I think you're meaning msbuild /t:restore , this one and dotnet restore can be suitable for your current situation. Also, they're suitable for that when you have dozens of projects in solution, but msbuild /t:restore and dotnet works for .net fx projects that use PackageReference instead of packages.config. So i ask in first comment whether you use packages.config or packagereference.Chickabiddy
Ah, duly noted, I did not consider that msbuild /t:restore only works for PackageReference. I appreciate all the provided solutions & options. I will work on this some more with the above info.Deodorize
C
3

As for your original issue: MSB4025

As you mentioned above, it's one open issue here. Anyone interested at it can track the issue there.

[error]The nuget command failed with exit code(1) and error(Unknown option: '-p:RestoreUseSkipNonexistentTargets=false')

The nuget restore command won't recognize a msbuild property. See similar issue and more details here.

Since The other project in the solution is a C# WinForms .NET Framework project. We're using packages.config rather than PackageReference.

A workaround for this is to use nuget custom command like this:

- task: NuGetCommand@2
  inputs:
    command: 'custom'
    arguments: 'restore YourProjectName\packages.config -PackagesDirectory $(Build.SourcesDirectory)\packages'

This can skip the restore step for the installer project.

Chickabiddy answered 20/12, 2019 at 15:33 Comment(1)
Another workaround is given here: github.com/microsoft/msbuild/issues/2064 Place a file with these contents next to your .sln file with the special name after.{yoursolutionname}.sln.targets Haven't tried it but this is probably the way to go when using PackageReference.Alisander
P
3

In general you do not need to called nuget restore explicitly anymore. MSBuild does it automatically as part of the build (so you're likely doing it twice). You can add the p:RestoreUseSkipNonexistentTargets=false property to the MSBuild arguments of a VSBuild task or a DotNet build or publish task:

- task: DotNetCoreCLI@2
  displayName: Build/Publish
  inputs:
    command: 'publish'
    publishWebProjects: false
    projects: '$(solution)'
    arguments: '-r $(runtimeIdentifier) /p:RestoreUseSkipNonexistentTargets=false'
    zipAfterPublish: false
    modifyOutputPath: false
Pessary answered 14/5, 2020 at 19:43 Comment(1)
This solved my problem, was doing a restore. Removing the restore step and turning off the build for the setup project in the solution configuration properties fixed it. Thanks.Bamby
P
1

The best way i found : use 3 tasks on the pipeline tested on vs2022 hosted image

All the tasks uses the Visual Studio 2022 Developer PowerShell.

Task 1 - restore nuget with ignoring the error of the unsupported vdproj Task 2 - Build the solution with msbuild will not build the vdproj Task 3 - Build the vdproj only using DevEnv

- task: PowerShell@2
  displayName: "restore nuget"
  inputs:
    targetType: 'inline'
    script: |
      & 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Launch-VsDevShell.ps1'
      msbuild -t:restore .\<solution>.sln -p:RestoreUseSkipNonexistentTargets=false
    ignoreLASTEXITCODE: true
    pwsh: true
- task: PowerShell@2
  displayName: "build solution"
  inputs:
    targetType: 'inline'
    script: |
      & 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Launch-VsDevShell.ps1'
      msbuild .\<solution>.sln
    pwsh: true
- task: PowerShell@2
  displayName: "create install "
  inputs:
    targetType: 'inline'
    script: |
      & 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Launch-VsDevShell.ps1'
      devenv ".\<project>.vdproj" /Build
    pwsh: true
Parabolic answered 12/6, 2022 at 14:53 Comment(0)
C
0

I'm also not using nuget restore. MSBuild is doing it automatically. It works for me in Projects with package.config and PackageReference, For command line, just add msbuld solution.sln -restore

Charybdis answered 9/9, 2024 at 9:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.