Msbuild: Failure using 15.8 RoslynCodeTaskFactory

Created on 10 Sep 2018  路  26Comments  路  Source: dotnet/msbuild

While trying to migrate off the NuGet package to the 15.8 RoslynCodeTask factory, I'm encountering issues getting the most basic tasks to work.

E.g. copying from the documentation https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-roslyncodetaskfactory?view=vs-2017#hello-world to a test.proj:

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
  <!-- This simple inline task displays "Hello, world!" -->  
  <UsingTask  
    TaskName="HelloWorld"  
    TaskFactory="RoslynCodeTaskFactory"  
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >  
    <ParameterGroup />  
    <Task>  
      <Reference Include="System.Xml"/>
      <Using Namespace="System"/>  
      <Using Namespace="System.IO"/>  
      <Code Type="Fragment" Language="cs">  
<![CDATA[  
// Display "Hello, world!"  
Log.LogError("Hello, world!");  
]]>  
      </Code>  
    </Task>  
  </UsingTask>  
    <Target Name="Hello">  
    <HelloWorld />  
  </Target>  
</Project>

Windows full framework (15.8.3):

"C:\Users\martin.ullrich\Downloads\testproj\test.proj" (Hello target) (1) ->
(Hello target) ->
  C:\Users\martin.ullrich\Downloads\testproj\test.proj(21,5): error MSB3755: Could not find reference "System.Xml". If this reference is required by your code, you may
 get compilation errors.
  C:\Users\martin.ullrich\Downloads\testproj\test.proj(21,5): error MSB4175: The task factory "RoslynCodeTaskFactory" could not be loaded from the assembly "C:\Program
 Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin\Microsoft.Build.Tasks.Core.dll". The task factory must return a value for the "TaskType" property
.

MacOS dotnet 2.1.401:

/Users/martin/tmp/testsln/test.proj/test.proj(21,5): error MSB3755: Could not find reference "System.Xml". If this reference is required by your code, you may get compilation errors.
/Users/martin/tmp/testsln/test.proj/test.proj(21,5): error MSB3755: Could not find reference "mscorlib". If this reference is required by your code, you may get compilation errors.
/Users/martin/tmp/testsln/test.proj/test.proj(21,5): error MSB3755: Could not find reference "netstandard". If this reference is required by your code, you may get compilation errors.
/Users/martin/tmp/testsln/test.proj/test.proj(21,5): error MSB4175: The task factory "RoslynCodeTaskFactory" could not be loaded from the assembly "/usr/local/share/dotnet/sdk/2.1.401/Microsoft.Build.Tasks.Core.dll". The task factory must return a value for the "TaskType" property.

cc @jeffkl

bug

Most helpful comment

I was also seeing this behavior with the same error message.

All 26 comments

I was also seeing this behavior with the same error message.

@jeffkl or @rainersigwald, @cdmihai could you please take a look?

It should be noted that the same code just works using the RoslynCodeTaskFactory NuGet package from https://github.com/jeffkl/RoslynCodeTaskFactory

I have the same problem, the project builds fine when using visual studio, but it will throw error when running cli 'dotnet build'.

The root cause of the bug is that the Microsoft.Build.Tasks project is copying the ref assemblies to its target framework output folder (net46 and netstandard2.0). The MSBuild project is then including them in the NuGet package for its target frameworks (net46, netcoreapp2.0, and netcoreapp2.1). So the files are in the correct place but aren't being included in the NuGet package.

So an easy workaround is to copy the ref folder from the full framework location ( the files are the same ) and we can look into fixing this for the next release of .NET Core.

I am using msbuild version 15.9.20+g88f5fadfbe with .netcore 2.1 and I am still experiencing error below. Any idea when it is being fixed?

error MSB4175: The task factory "RoslynCodeTaskFactory" could not be loaded from the assembly "C:Program
Files (x86)Microsoft Visual Studio2017EnterpriseMSBuild15.0binMicrosoft.Build.Tasks.Core.dll". The task factory must return a value for the "TaskType" property.

For now, my workaround is still to reference external dependency from https://github.com/jeffkl/RoslynCodeTaskFactory

@radical I'm also seeing this in the msbuild 16.0.42-preview+g804bde742b bundled with Mono 5.18.0.234

Until the fix is released, is there a workaround for this?

Argh, still seeing this issue in VS 2019 (16.0.0). Any System.* <Reference>s that I try to add to an inline task in my .NET Standard project are yielding:

Could not find reference "System.*". If this reference is required by your code, you may get compilation errors.

@jeffkl @rainersigwald Are there other reports of a regression with this?

Do you need these references? They shouldn鈥檛 be necessary since all the surface area should be covered by netstandard.dll and mscorlib.dll

@dasMulli Having the same issue as @DanVicarel but on macOS.
It also throws errors on mscorlib and netstandard hence the error of RoslynCodeTaskFactory.

error MSB3755: Could not find reference "mscorlib". If this reference is required by your code, you may get compilation errors]
error MSB3755: Could not find reference "netstandard". If this reference is required by your code, you may get compilation errors.
error MSB4175: The task factory "RoslynCodeTaskFactory" could not be loaded from the assembly "/usr/local/share/dotnet/sdk/2.2.103/Microsoft.Build.Tasks.Core.dll". The task factory must return a value for the "TaskType" property.

@thomasvdb SDK 2.2.103 includes MSBuild 15.9, but this was fixed only in MSBuild 16.0 (in SDK 2.2.200 and higher).

I am still getting this problem using MSBuild bundled with the latest .NET Core release (downloaded using dotnet-install.ps1) using MSBuild (.NET Core) version 16.1.19!

@rainersigwald Still experiencing this error.

dotnet --list-sdks
2.2.402 [/usr/local/share/dotnet/sdk]
3.0.100 [/usr/local/share/dotnet/sdk]

I don't experience this error in JetBrains Rider however. Is there something else I could check?

@rainersigwald we observe the same problem on msbuild coming with VS 2019 (16.5.).

@hokb What problem, exactly?

@rainersigwald we see the same issues as the OP: https://github.com/microsoft/msbuild/issues/3726#issue-358472792

I was trying to use RoslynCodeTastFactory in the msbuild project of a simple .NET Core DLL project.
The most simple 'HelloWorld' example from https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-roslyncodetaskfactory?view=vs-2019 creates these errors:

Error MSB4175 The task factory "RoslynCodeTaskFactory" could not be loaded from the assembly "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Build.Tasks.Core.dll". The task factory must return a value for the "TaskType" property. ConsoleApp2 C:\user1\source\repos\ConsoleApp2\ConsoleApp2.csproj
Error MSB3755 Could not find reference "System.Xml". If this reference is required by your code, you may get compilation errors. ConsoleApp2 C:\User1\source\repos\ConsoleApp2\ConsoleApp2.csproj
Am I missing something?

I think that's a documentation bug, you shouldn't need to reference System.Xml. Try removing:

<Reference Include="System.Xml"/>

You are right! I was not aware that the references are not taken from the GAC here. A valid file system path to the reference(s) dlls makes both errors go away - and the task complete. Thanks!

@jeffkl
@hokb
How to reference nuget package?
Do I need to specify the full path like C:\Users\Den\.nuget\packages\newtonsoft.json\12.0.3\lib\netstandard2.0\Newtonsoft.Json.dll ?

Yes you'll have to reference the full path to the DLL. It is not recommended to use RoslynCodeTaskFactory for complex tasks, instead you should compile a real task assembly which can reference anything you want, have unit tests, etc.

Damn! What am I doing wrong?

I have msbuild script:

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

    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Newtonsoft.Json" Version="12.0.3">
          <GeneratePathProperty>true</GeneratePathProperty>
        </PackageReference>
    </ItemGroup>


    <UsingTask TaskName="MyTask" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
        <ParameterGroup />
        <Task>
            <Reference Include="C:\Users\Den\.nuget\packages\newtonsoft.json\12.0.3\lib\netstandard2.0\Newtonsoft.Json.dll" />
            <Code Type="Fragment" Language="cs">
<![CDATA[
Log.LogMessage( MessageImportance.High, typeof( Newtonsoft.Json.JsonConvert ).ToString() );
]]>
            </Code>
        </Task>
    </UsingTask>

    <Target Name="_BeforeBuild" BeforeTargets="BeforeBuild">
        <Message Text="BeforeBuild" Importance="high" />
        <MyTask />
    </Target>


</Project>

This results in the error:

System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. 袧械 褍写邪械褌褋褟 薪邪泄褌懈 褍泻邪蟹邪薪薪褘泄 褎邪泄谢.
File name: 'Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'
   at InlineCode.MyTask.Execute()
   at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

=== Pre-bind state information ===
LOG: DisplayName = Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
 (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/MSBuild/Current/Bin/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin\MSBuild.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/MSBuild/Current/Bin/Newtonsoft.Json.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/MSBuild/Current/Bin/Newtonsoft.Json/Newtonsoft.Json.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/MSBuild/Current/Bin/Newtonsoft.Json.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/MSBuild/Current/Bin/Newtonsoft.Json/Newtonsoft.Json.EXE.
    MSBuild     MSBuildExample  C:\Users\Den\Desktop\MSBuildExample\MSBuildExample\MSBuildExample.csproj    31

Normal tasks in MSBuild are loaded in a way that their dependencies are also loaded from the same directory. Tasks created with a custom "task host" such as RoslynCodeTaskFactory do not get this logic for free. You'll need to load your dependencies manually since the host executable is MSBuild.exe and .NET CLR assembly loading rules only load dependencies next to the running executable.

https://docs.microsoft.com/en-us/dotnet/standard/assembly/resolve-loads

@jeffkl
I even can't make normal task work.
How to specify reference for normal task? I've tried these cases but they don't work.

1)

<UsingTask TaskName="Lib.Tasks.MyTask" AssemblyFile="$(SolutionDir)\Lib\bin\Debug\netstandard2.0\Lib.dll" >
    <Reference Include="$(NugetPackageRoot)\mono.cecil\0.11.3\lib\netstandard2.0\Mono.Cecil.dll" />
</UsingTask>
Error: The element <Reference> beneath element <UsingTask> is unrecognized.

2)

<UsingTask TaskName="Lib.Tasks.MyTask" AssemblyFile="$(SolutionDir)\Lib\bin\Debug\netstandard2.0\Lib.dll" >
    <Task>
        <Reference Include="$(NugetPackageRoot)\mono.cecil\0.11.3\lib\netstandard2.0\Mono.Cecil.dll" />
    </Task>
</UsingTask>
Error: The required attribute "TaskFactory" is empty or missing from the element <UsingTask>.

@Denis535 You'll need to make those assemblies available next to the task assembly, perhaps by pointing at the published output.

@rainersigwald
Is it not possible to specify reference for normal UsingTask?
Also, the problem is that the error doesn't tell me which dependencies cannot be loaded.
P.S. It would be easier if the PackageReference supported "CopyLocal=true".
P.P.S. It looks like I only have one way - to make a nuget package.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  4Comments

ctolkien picture ctolkien  路  4Comments

KirillOsenkov picture KirillOsenkov  路  3Comments

twenzel picture twenzel  路  4Comments

rainersigwald picture rainersigwald  路  3Comments