简体   繁体   中英

Nuget Update Packages.config in MSBuild BeforeBuild Step

I have been trying to write an MsBuild task to automatically get Nuget packages from a feed url and automatically update the packages.config to update to the latest version.

 // ---- 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));
    }
  }

This is working fine as a console app and is automatically reading the file correctly and updating the necessary references.

When i try to run this as an MsBuild task I keep running into errors.

  • An error has occurred during compilation. c:\\Users\\user\\AppData\\Local\\Temp\\dkkg20ya.0.cs(22,11) : error CS0246: The type or namespace name 'NuGet' could not be found (are you missing a using directive or an assembly reference?)
  • The task factory "CodeTaskFactory" could not be loaded from the assembly "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\MSBuild\\15.0\\Bin\\Microsoft.Build.Tasks.v15.0.dll". The task factory must return a value for the "TaskType" property.

This is the code I have put in the csproj (also moved to the nuget.targets to test)

<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>

Any ideas on how to resolve this as cannot seem to find a solution. Overall what to run this a pre step on a CI build to keep nugets up to date.

Thanks Tim

Just call

nuget restore "your_solution.sln"

Don't reinvent the wheel by writing it in C# code.

Nuget Update Packages.config in MSBuild BeforeBuild Step

Not sure where your code issue comes from. It may be simpler just use NuGet.exe to restore and update the solution instead of trying to use C# code.

So you could add following nuget command line in the MSBuild BeforeBuild Step

  <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>

Note: If you are using Visual Studio, Visual Studio will automatically check the missing packages during the build and restore them: Package Restore .

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM