Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a custom task via UsingTask in .NET Core keeps failing to build (missing assemblies)

Tags:

.net-core

My goal is to run tasks in .NET Core (akin to rake in Rails land), so I can execute code outside the normal control flow of the application's lifecycle. I have seen there are projects like albacore that supposedly accomplish this, but I'm trying to do it "the .NET way", rather than bringing in a separate ruby dependency to accomplish this.

After following this article on Task Writing for msbuild, I have managed to create a simple Task that implements the ITask interface as suggested in the article:

EcommerceSite/Tasks/ScrapeAll.cs

using System;
using Microsoft.Build.Framework;  
using Microsoft.Build.Utilities;

namespace Tasks
{
    public class ScrapeAll : Task
    {
        public override bool Execute()
        {
            return true;
        }
    }
}

My .csproj file uses the UsingTask element to register my task code, and I have a Target that invokes the task:

EcommerceSite/EcommerceSite.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup> 

  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.1.1" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.3" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.0" />
    <PackageReference Include="Microsoft.Build.Framework" Version="15.3.409" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.3.409" />
  </ItemGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="Views\ItemPage\" />
    <Folder Include="Tasks\" />
  </ItemGroup>

  <UsingTask TaskName="Tasks.ScrapeAll" AssemblyFile="bin/Debug/netcoreapp2.0/EcommerceSite.dll" />

  <Target Name="ScrapeAll">
    <Tasks.ScrapeAll />
  </Target>
</Project>

So now, on my command line, I am able to invoke: dotnet msbuild /t:ScrapeAll and yet, I get this error:

error MSB4062: The "Tasks.ScrapeAll" task could not be loaded from the assembly 
[redacted]/EcommerceSite/bin/Debug/netcoreapp2.0/EcommerceSite.dll. 
Could not load file or assembly 'Microsoft.AspNetCore.Mvc.ViewFeatures, 
Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. 
The system cannot find the file specified.

[redacted]/EcommerceSite/EcommerceSite.csproj(33,5): error MSB4062:  
Confirm that the <UsingTask> declaration is correct, that the assembly and all its dependencies are available, 
and that the task contains a public class that implements Microsoft.Build.Framework.ITask

So my questions are:

  1. Why is my Task trying to load Microsoft.AspNetCore.Mvc.ViewFeatures, which according to the NuGet docs, contains:

    view rendering features such as view engines, views, view components, and HTML helpers

of which my Task does nothing of the sort?

  1. How do I make it try to load this assembly, or if that is not an option, how do I resolve the dependency issue?
like image 974
Peter Avatar asked Oct 18 '22 03:10

Peter


1 Answers

I got this working tonight. You can see my solution here.

In essence, I hit 2 problems:

  1. I was including the namespace in the element. Once I remove that and just used the class name, the error went away.
<UsingTask TaskName="PublishValidationTask"
AssemblyFile="C:\git\CustomBuildTargets\PublishPipelineTesting\bin\debug\netcoreapp2.0\PublishPipelineTesting.dll"
/>
  1. Only when I set Importance="High" would text show up on the command line.
C:\git\CustomBuildTargets\PublishPipelineTesting>dotnet msbuild PublishPipelineTesting.csproj
Microsoft (R) Build Engine version 15.7.179.6572 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  PublishPipelineTesting -> C:\git\CustomBuildTargets\PublishPipelineTesting\bin\Debug\netcoreapp2.0\PublishPipelineTesting.dll
  This is a test
  Hello World
  1. Paths also made things weird. I started with an absolute path, which worked well. From there I was able to figure out the relative path, which was simply starting in the bin directory:

AssemblyFile="bin\debug\netcoreapp2.0\PublishPipelineTesting.dll" />

Once I got that working, and the custom task running, return true/false would allow the build to pass or fail, which is exactly what I wanted. When returning "false", I would now get:

C:\git\CustomBuildTargets\PublishPipelineTesting>dotnet run PublishPipelineTesting.csproj

The build failed. Please fix the build errors and run again.

When return true out of the task, the build would pass and the project would run:

C:\git\CustomBuildTargets\PublishPipelineTesting>dotnet run PublishPipelineTesting.csproj
Hello World!

like image 180
Chris M. Avatar answered Oct 21 '22 09:10

Chris M.