【发布时间】: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
.csprojformat,它摆脱了旧的.nuspec和packages.config垃圾。如果没有,请阅读The right way to restore NuGet packages。无论哪种方式,这是 MSBuild 的内置功能,您正在通过构建任务重新发明轮子。 -
这是一个 web 项目,我们已经在 sln 中有一个 csproj。我知道 MsBuild 可以自动恢复包。我需要自动将包更新到 nuget 提要上可用的最新版本
-
哎呀!这听起来像是导致不稳定的秘诀。
标签: c# visual-studio msbuild nuget