【问题标题】:Nuget Update Packages.config in MSBuild BeforeBuild StepMSBuild BeforeBuild 步骤中的 Nuget 更新 Packages.config
【发布时间】:2018-03-19 12:10:14
【问题描述】:

我一直在尝试编写一个 MsBuild 任务来自动从提要 url 获取 Nuget 包并自动更新 packages.config 以更新到最新版本。

 // ---- Download and install a package at a desired path ----
  var sourceUri = new Uri("FEED URL");

  // ---- Update the ‘packages.config’ file ----
  var packageReferenceFile = new PackageReferenceFile("../../packages.config");
  string packagesPath = "../../packages";
  IPackageRepository sourceRepository = PackageRepositoryFactory.Default.CreateRepository(sourceUri.ToString());
  PackageManager packageManager = new PackageManager(sourceRepository, packagesPath);

  foreach (var sourcePackage in sourceRepository.GetPackages().Where(x => x.IsLatestVersion))
  {
    if (!packageReferenceFile.EntryExists(sourcePackage.Id + " " + sourcePackage.Version, sourcePackage.Version))
    {
      var oldPackage = packageReferenceFile.GetPackageReferences().FirstOrDefault(x => x.Id.Contains(sourcePackage.Id));

      if (oldPackage != null)
      {
        packageReferenceFile.DeleteEntry(oldPackage.Id, oldPackage.Version);
      }

      packageManager.InstallPackage(sourcePackage.Id, SemanticVersion.Parse(sourcePackage.Version.ToFullString()));

      // Get the target framework of the current project to add --> targetframework="net452" attribute in the package.config file
      var currentTargetFw = Assembly.GetExecutingAssembly()
        .GetCustomAttributes(typeof(TargetFrameworkAttribute), false);
      var targetFrameworkAttribute = ((TargetFrameworkAttribute[]) currentTargetFw).FirstOrDefault();

      // Update the packages.config file    
      packageReferenceFile.AddEntry(sourcePackage.GetFullName(),
        SemanticVersion.Parse(sourcePackage.Version.ToFullString()), false,
        new FrameworkName(targetFrameworkAttribute.FrameworkName));
    }
  }

这作为控制台应用程序运行良好,并且会自动正确读取文件并更新必要的引用。

当我尝试将此作为 MsBuild 任务运行时,我一直遇到错误。

  • 编译过程中出现错误。 c:\Users\user\AppData\Local\Temp\dkkg20ya.0.cs(22,11):错误 CS0246:找不到类型或命名空间名称“NuGet”(您是否缺少 using 指令或程序集引用?)
  • 无法从程序集“C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Build.Tasks.v15.0 加载任务工厂“CodeTaskFactory”。 dll”。任务工厂必须为“TaskType”属性返回一个值。

这是我放在csproj中的代码(也移到nuget.targets进行测试)

<Target Name="BeforeBeforeBuild" BeforeTargets="BeforeBuild">
    <UpdateNugetFiles />
  </Target>
<UsingTask TaskName="UpdateNugetFiles" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll" > 
    <Task>
        <Reference Include="System.Core" />
        <Using Namespace="System" />
        <Using Namespace="System.Linq" />
        <Using Namespace="System.Reflection" />
        <Using Namespace="System.Runtime.Versioning" />
        <Using Namespace="NuGet" />
        <Code Type="Fragment" Language="cs">
            <![CDATA[
            try {
                // ---- Download and install a package at a desired path ----
  var sourceUri = new Uri("FEED URL");

  // ---- Update the ‘packages.config’ file ----
  var packageReferenceFile = new PackageReferenceFile("../../packages.config");
  string packagesPath = "../../packages";
  IPackageRepository sourceRepository = PackageRepositoryFactory.Default.CreateRepository(sourceUri.ToString());
  PackageManager packageManager = new PackageManager(sourceRepository, packagesPath);

  foreach (var sourcePackage in sourceRepository.GetPackages().Where(x => x.IsLatestVersion))
  {
    if (!packageReferenceFile.EntryExists(sourcePackage.Id + " " + sourcePackage.Version, sourcePackage.Version))
    {
      var oldPackage = packageReferenceFile.GetPackageReferences().FirstOrDefault(x => x.Id.Contains(sourcePackage.Id));

      if (oldPackage != null)
      {
        packageReferenceFile.DeleteEntry(oldPackage.Id, oldPackage.Version);
      }

      packageManager.InstallPackage(sourcePackage.Id, SemanticVersion.Parse(sourcePackage.Version.ToFullString()));

      // Get the target framework of the current project to add targetframework="net452" attribute in the package.config file
      currentTargetFw = Assembly.GetExecutingAssembly()
        .GetCustomAttributes(typeof(TargetFrameworkAttribute), false);
      var targetFrameworkAttribute = ((TargetFrameworkAttribute[]) currentTargetFw).FirstOrDefault();

      // Update the packages.config file    
      packageReferenceFile.AddEntry(sourcePackage.GetFullName(),
        SemanticVersion.Parse(sourcePackage.Version.ToFullString()), false,
        new FrameworkName(targetFrameworkAttribute.FrameworkName));
    }
  }

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

有关如何解决此问题的任何想法似乎都找不到解决方案。 总体而言,在 CI 构建上运行此步骤以使 nuget 保持最新。

谢谢 蒂姆

【问题讨论】:

  • 如果这是一个类库,你真的应该upgrade to the new .csproj format,它摆脱了旧的.nuspecpackages.config垃圾。如果没有,请阅读The right way to restore NuGet packages。无论哪种方式,这是 MSBuild 的内置功能,您正在通过构建任务重新发明轮子。
  • 这是一个 web 项目,我们已经在 sln 中有一个 csproj。我知道 MsBuild 可以自动恢复包。我需要自动将包更新到 nuget 提要上可用的最新版本
  • 哎呀!这听起来像是导致不稳定的秘诀。

标签: c# visual-studio msbuild nuget


【解决方案1】:

打电话就行了

nuget restore "your_solution.sln"

不要用 C# 代码重新发明轮子。

【讨论】:

  • 别忘了添加您的 nuget.config 文件以指定提要的位置。
【解决方案2】:

MSBuild BeforeBuild 步骤中的 Nuget 更新 Packages.config

不确定您的代码问题来自何处。使用NuGet.exe 来恢复和更新解决方案可能更简单,而不是尝试使用 C# 代码。

因此您可以在 MSBuild BeforeBuild 步骤中添加以下 nuget 命令行

  <Target Name="BeforeBeforeBuild" BeforeTargets="BeforeBuild">
    <Exec Command="$(YourNuGetPath)\nuget.exe restore &quot;$(YouSolutionPath)\YourSolution.sln&quot; -PackagesDirectory &quot;$(YouPackagePath)\packages&quot;" />
    <Exec Command="$(YourNuGetPath)\nuget.exe update &quot;$(YouSolutionPath)\YourSolution.sln&quot;" />
  </Target>

注意:如果您使用的是 Visual Studio,Visual Studio 会在构建过程中自动检查丢失的包并恢复它们:Package Restore

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-29
    • 2021-02-23
    • 1970-01-01
    • 2011-10-16
    • 2017-09-24
    • 1970-01-01
    • 2016-02-10
    • 2013-09-17
    相关资源
    最近更新 更多