Home > Back-end >  Azure Pipelines Nuget Restore Failing MSB4226
Azure Pipelines Nuget Restore Failing MSB4226

Time:12-15

I am trying to set up an Azure pipeline for a project but I am getting a failure on the nuget restore command in my yml. Below is the full error:

[error]The nuget command failed with exit code(1) and error(D:\a\1\s\UDesign\Backup\UDesign\UDesign.csproj(190,11): error MSB4226: The imported project "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" was not found. Also, tried to find "Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" in the fallback search path(s) for $(MSBuildExtensionsPath32) - "C:\Program Files (x86)\MSBuild" . These search paths are defined in "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\msbuild.exe.Config". Confirm that the path in the declaration is correct, and that the file exists on disk in one of the search paths.) ##[error]Packages failed to restore

Pretty much every post on this error is on the Build command in the YML but this is failing on the Nuget Restore:

Pipelines failure image

YML below:

# .NET Desktop
# Build and run tests for .NET Desktop or Windows classic desktop solutions.
# Add steps that publish symbols, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net

trigger:
- master

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:
- task: NuGetToolInstaller@1

- task: NuGetCommand@2
  inputs:
    command: 'restore'
    restoreSolution: '$(solution)'
    feedsToUse: 'select'
    vstsFeed: 'MyFeed'

- task: VSBuild@1
  inputs:
    solution: '$(solution)'
    msbuildArgs: '/p:OutputPath="$(Build.BinariesDirectory)\$(Build.BuildID)"'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'
    restoreNugetPackages: true
    msbuildArchitecture: 'x64'

- task: ArchiveFiles@2
  inputs:
    rootFolderOrFile: '$(Build.BinariesDirectory)\$(Build.BuildId)'
    includeRootFolder: false
    archiveType: 'zip'
    archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
    replaceExistingArchive: true

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'

I am not sure if the issue is with the config somehow or my NuGet packages, I can't find much on this issue.

CodePudding user response:

Could you please try this

Note: You need to replace the source and target paths according to your project.

variables:
- name: BuildParameters.RestoreBuildProjects
  value: '**/*.csproj'
- name: BuildParameters.TestProjects
  value: '**/*[Tt]ests/*.csproj'
trigger:
  branches:
    include:
    - refs/heads/master
name: $(date:yyyyMMdd)$(rev:.r)
jobs:
- job: Job_1
  displayName: Agent job 1
  pool:
    vmImage: windows-2019
  steps:
  - checkout: self
  - task: DotNetCoreCLI@2
    displayName: Restore
    inputs:
      command: restore
      projects: $(BuildParameters.RestoreBuildProjects)
  - task: DotNetCoreCLI@2
    displayName: Build
    inputs:
      projects: $(BuildParameters.RestoreBuildProjects)
      arguments: --configuration $(BuildConfiguration)
  - task: DotNetCoreCLI@2
    displayName: Test
    enabled: False
    inputs:
      command: test
      projects: $(BuildParameters.TestProjects)
      arguments: --configuration $(BuildConfiguration)
  - task: DotNetCoreCLI@2
    displayName: Publish
    inputs:
      command: publish
      publishWebProjects: True
      projects: $(BuildParameters.RestoreBuildProjects)
      arguments: --configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)
      zipAfterPublish: True
  - task: PublishBuildArtifacts@1
    displayName: Publish Artifact
    condition: succeededOrFailed()
    inputs:
      PathtoPublish: $(build.artifactstagingdirectory)
      TargetPath: '\\my\share\$(Build.DefinitionName)\$(Build.BuildNumber)'
...

CodePudding user response:

Actual issue

The problem is actually unrelated to NuGet, it's just that NuGet is the first thing in your pipeline that tries to evaluate MSBuild files. If you look carefully at the error:

error MSB4226: The imported project "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" was not found.

You can see that the error is that MSBuild can't find Microsoft.WebApplication.targets. What does this mean? I'm not 100% confident, but I do have high confidence that this means you're using a "self hosted" CI agent, not a Microsoft hosted agent, and whoever set up the machine installed Visual Studio 2019 without installing the ASP.NET workload. Therefore, whoever sets up your CI agents should install the "ASP.NET and web development" workload.

Suggestion 1: CI agent should use BuildTools SKU

If you look at VS's release and build history, you see for every version, under "Links to Installer", there's a "BuildTools" link. This is a subset of Visual Studio without all the GUI stuff, meant for CI agents specifically. I don't think the BuildTools SKU has workload options, it just installs all the build tools necessary for all workloads.

Only in rare circumstances is the "full" Visual Studio required on a CI agent, so unless you know you're in that circumstance, I suggest installing the BuildTools on your CI agent instead of Enterprise or Professional.

Suggestion 2: Don't use NuGetCommand

Someone from the Azure DevOps team told my team that they want to deprecate these "heavy" tasks, and suggest customers call commands directly in a script task. In particular, the way they implemented these features will break NuGet's new Package Source Mapping feature.

If your solution contains only SDK style projects, then I suggest you use:

- task: NuGetAuthenticate
  displayName: Set up NuGet authentication
- script: dotnet restore $(solution)
  displayName: Restore

If your solution contains any "legacy" (non-SDK style) projects, then instead of using the dotnet CLI, use - script: msbuild -t:restore $(solution).

Suggestion 3: Don't use VSBuild

You're using the task VSBuild to run your build. This is a task that uses devenv.com to build the project. While devenv does have command line parameters to build from the command line, msbuild.exe is the "official" tool to do command line builds. Again, unless you know you're in a special circumstance that really needs to be built via devenv /build, I suggest you use the dotnet CLI or MSBuild instead. As previously mentioned, the Azure DevOps team apparently want to deprecate the "heavy" tasks, so I suggest you use a script and call dotnet or msbuild directly.

- script: msbuild -t:build $(solution)
  displayName: Build solution
  • Related