NuGet Restore使用MSBuild

时间:2016-12-05 10:16:33

标签: visual-studio tfs msbuild nuget nuget-package-restore

我有一个ASP.NET MVC 5项目,我正在尝试使用MSBuild在我们的公司构建服务器上构建,但是构建无法恢复NuGet包。我正在使用Visual Studio 2015和TFS。

我的项目结构如下:

  • 解决方案(.sln)
  • .nuget
    • NuGet.config
    • NuGet.targets
  • 项目文件夹
    • 项目项目(参考,图书馆等)
  • Project.Test.Unit
    • 单元测试项目

这是我的 NuGet.config 文件:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
  </solution>
</configuration>

这是 NuGet.targets 文件:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>

    <!-- Enable the restore command to run before builds -->
    <RestorePackages Condition="  '$(RestorePackages)' == '' ">true</RestorePackages>

    <!-- Property that enables building a package from a project -->
    <BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>

    <!-- Determines if package restore consent is required to restore packages -->
    <RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">false</RequireRestoreConsent>

    <!-- Download NuGet.exe if it does not already exist -->
    <DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
  </PropertyGroup>

  <ItemGroup Condition=" '$(PackageSources)' == '' ">
    <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
    <!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
    <!--
            <PackageSource Include="https://www.nuget.org/api/v2/" />
            <PackageSource Include="https://my-nuget-source/nuget/" />
        -->
    <PackageSource Include="\\itliv-nas03\Development Team\NuGet\Packages" />
  </ItemGroup>

  <PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
    <!-- Windows specific commands -->
    <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
    <PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
  </PropertyGroup>

  <PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
    <!-- We need to launch nuget.exe with the mono command if we're not on windows -->
    <NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
    <PackagesConfig>packages.config</PackagesConfig>
  </PropertyGroup>

  <PropertyGroup>
    <!-- NuGet command -->
    <NuGetExePath Condition=" '$(NuGetExePath)' == '' ">\\itliv-nas03\Development Team\NuGet\NuGet.exe</NuGetExePath>
    <PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>

    <NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
    <NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>

    <PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>

    <RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
    <NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>

    <PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
    <PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>

    <!-- Commands -->
    <RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)"  $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
    <BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>

    <!-- We need to ensure packages are restored prior to assembly resolve -->
    <BuildDependsOn Condition="$(RestorePackages) == 'true'">
      RestorePackages;
      $(BuildDependsOn);
    </BuildDependsOn>

    <!-- Make the build depend on restore packages -->
    <BuildDependsOn Condition="$(BuildPackage) == 'true'">
      $(BuildDependsOn);
      BuildPackage;
    </BuildDependsOn>
  </PropertyGroup>

  <Target Name="CheckPrerequisites">
    <!-- Raise an error if we're unable to locate nuget.exe  -->
    <Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
    <!--
        Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
        This effectively acts as a lock that makes sure that the download operation will only happen once and all
        parallel builds will have to wait for it to complete.
        -->
    <MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
  </Target>

  <Target Name="_DownloadNuGet">
    <DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
  </Target>

  <Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
    <Exec Command="$(RestoreCommand)"
          Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />

    <Exec Command="$(RestoreCommand)"
          LogStandardErrorAsError="true"
          Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
  </Target>

  <Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
    <Exec Command="$(BuildCommand)"
          Condition=" '$(OS)' != 'Windows_NT' " />

    <Exec Command="$(BuildCommand)"
          LogStandardErrorAsError="true"
          Condition=" '$(OS)' == 'Windows_NT' " />
  </Target>

  <UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <OutputFilename ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="System.Core" />
      <Using Namespace="System" />
      <Using Namespace="System.IO" />
      <Using Namespace="System.Net" />
      <Using Namespace="Microsoft.Build.Framework" />
      <Using Namespace="Microsoft.Build.Utilities" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[
                try {
                    OutputFilename = Path.GetFullPath(OutputFilename);

                    Log.LogMessage("Downloading latest version of NuGet.exe...");
                    WebClient webClient = new WebClient();
                    webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);

                    return true;
                }
                catch (Exception ex) {
                    Log.LogErrorFromException(ex);
                    return false;
                }
            ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

我尝试了以下内容:

将此代码添加到NuGet.config文件中:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
  </solution>
  <packageSources>
    <add key="itliv" value="\\itliv-nas03\Development Team\NuGet\Packages" />
  </packageSources>
  <activePackageSource>
    <add key="All" value="\\itliv-nas03\Development Team\NuGet\Packages" />
  </activePackageSource>
</configuration>
  • 尝试使用以下命令行:

nuget restore path\to\solution.sln返回以下错误:

WARNING: Unable to find version '3.4.1.9004' of package 'Antlr'.
  C:\Users\it-chrism\.nuget\packages\: Package 'Antlr.3.4.1.9004' is not found on source 'C:\Users\it-chrism\.nuget\packages\'.
  C:\Users\it-chrism\AppData\Local\NuGet\Cache: Package 'Antlr.3.4.1.9004' is not found on source 'C:\Users\it-chrism\AppData\Local\NuGet\Cache'.

尝试构建时,以下是错误消息

Summary
Release | Any CPU
 1 error(s), 0 warning(s)
$/Develop/Websites/VehicleLookupUI/VehicleLookupWebUI.sln - 1 error(s), 0 warning(s), View Log File
 C:\Builds\1\Develop\VehicleLookupWeb-Develop\Sources\VehicleLookupUI\VehicleLookupWebUI\VehicleLookupWebUI.csproj (315): This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is ..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props.
 $/Develop/Websites/VehicleLookupUI/VehicleLookupWebUI.sln compiled
 No Test Results
 No Code Coverage Results
Other Errors and Warnings
 2 error(s), 0 warning(s)
 Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.

 TF270015: 'MSBuild.exe' returned an unexpected exit code. Expected '0'; actual '1'.

我有一种感觉,NuGet正在寻找丢失包的错误文件夹。我可以在工具&gt;中包含这些来源NuGet包管理器..&gt;包管理器设置&gt; NuGet包管理器&gt;包源但这仅适用于我在本地使用Visual Studio而不是使用MSBuild尝试构建它并开箱即用。

我试图通过打开Team Explorer&gt;来构建TSF。构建,然后右键单击我的构建并选择Queue New Build ...

2 个答案:

答案 0 :(得分:2)

您正在使用MSBuild-Integrated方式恢复包,这样,解决方案中就有.nuget文件夹(包含nugget.exe,nugget.config和nugget.targets),需要添加到源代码管理中不需要在构建定义中添加Nuget Restore构建步骤/任务来恢复包,因此删除该步骤/任务并在构建定义的Repository选项卡中将Clean设置为true。 我建议您迁移到自动恢复:

  1. 关闭Visual Studio以避免文件潜在的文件锁定和冲突。
  2. 如果使用TFS:a。从解决方案的.nuget文件夹中删除nuget.exe和nuget.targets,然后从解决方案工作区中删除这些文件。一个。使用disableSourceControlIntegration设置保留nuget.config,如使用Team Foundation版本控制省略包中所述。
  3. 如果不使用TFS:a。从解决方案和解决方案工作区中删除.nuget文件夹。
  4. 编辑解决方案中的每个项目文件,删除&lt; RestorePackages&gt;元素,并删除对nuget.targets文件的任何引用。
  5. 更多信息,请参阅this文章。

答案 1 :(得分:0)

请在以下位置的TFS构建服务器上使用特殊的Nuget.config文件。 enter image description here