sdk: dotnet run don't copy files marked as CopyToOutputDirectory=Always to output on Azure Pipelines hosted agents

I have a test pipeline on hosted agents: ConsoleApp-Win-Core-BothFiles-net5. Pipeline does following steps:

  1. downloads dll file from another pipeline

  2. downloads dylib file from another pipeline

  3. creates console app via dotnet new console -n ConsoleApp

  4. copies dll and dylib files into ConsoleApp folder placing them near csproj file:

    Copy-Item test.dylib -Destination ConsoleApp
    Copy-Item test.dll -Destination ConsoleApp
    
  5. sets csproj file content:

    $content = @"
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <None Update="test.dll">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </None>
        <None Update="test.dylib">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </None>
      </ItemGroup>
    
    </Project>
    "@
    
    Set-Content -Path ConsoleApp/ConsoleApp.csproj -Value $content
    

    so we have <CopyToOutputDirectory>Always</CopyToOutputDirectory> here.

  6. sets Program.cs content:

    $content = @"
    using System;
    using System.Globalization;
    using System.Runtime.InteropServices;
    using System.Threading;
    
    namespace ConsoleNetFramework
    {
        class Program
        {
            [DllImport("test")]
            public static extern int Foo();
    
            static void Main(string[] args)
            {
                var result = Foo();
                Console.WriteLine($"Result = {result}");
            }
        }
    }
    "@
    
    Set-Content -Path ConsoleApp/Program.cs -Value $content
    
  7. runs app via .NET Core task (dotnet run --project ConsoleApp/ConsoleApp.csproj)

And here we get the error:

Unhandled exception. System.DllNotFoundException: Unable to load DLL 'test' or one of its dependencies: Access is denied. (0x80070005 (E_ACCESSDENIED))
   at ConsoleNetFramework.Program.Foo()
   at ConsoleNetFramework.Program.Main(String[] args) in D:\a\1\s\ConsoleApp\Program.cs:line 15

I found that this is due to files were not copied to output directory.

So I added additional step that prints all dll and dylib files:

----                -------------         ------ ----                                                                  
-a----        5/19/2021   2:42 PM           5120 ConsoleApp.dll                                                        


    Directory: D:\a\1\s\ConsoleApp\bin\Debug\net5.0


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-a----        5/19/2021   2:42 PM           4608 ConsoleApp.dll                                                        


    Directory: D:\a\1\s\ConsoleApp\obj\Debug\net5.0\ref


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-a----        5/19/2021   2:42 PM           5120 ConsoleApp.dll                                                        


    Directory: D:\a\1\s\ConsoleApp\obj\Debug\net5.0


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-a----        5/19/2021   2:42 PM           4608 ConsoleApp.dll                                                        


    Directory: D:\a\1\s\ConsoleApp


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
d-----        5/19/2021   2:41 PM                test.dll                                                              
d-----        5/19/2021   2:41 PM                test.dylib                                                            


Finishing: Print all dll and dylib files
Row 7. Clickable

Row 2. Clickable

Row 2. Clickable

Row 2. Clickable

Task disabled

Task enabled

Row 2. Clickable

For some reason I see only dll and dylib near csproj that I added on fourth step. So my question is why files were not copied to output directory (D:\a\1\s\ConsoleApp\obj\Debug\net5.0)?

When I do all these steps locally on my computer, all works fine.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (10 by maintainers)

Most upvoted comments

I’m not sure why but Azure Pipeline’s is having an issue with the below configuration:

<ItemGroup>
  <Content Include="dist\**">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <PackageCopyToOutput>true</PackageCopyToOutput>
  </Content>
</ItemGroup>

<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
  <Exec Command="yarn build" />
</Target>

The files created by “yarn build” are not seen by the Content-Include statement above. I had to remove the PreBuild task and add it as a separate Pipeline task before the DotNetCli task.

I discovered this by manually creating a dist folder with a “dist” file (due to GIT limitations) and it seems the yarn build deleted that file and the build agent complained because it couldn’t find it.

I do not get this functionality locally or when running dotnet publish ... on the build agent server manually from command prompt.

No, the way it works is None items are automatically created for files, not directories. This is the reason you didn’t see the None items and Update didn’t do anything. When you changed to Include, you forced including the directory, so the Copy task failed.

I’ll take a look at the online viewer failure.

You can add this at the end of your .csproj:

  <ItemGroup>
    <AllFiles Include="**\*" />
  </ItemGroup>

and then in the binlog viewer, search for $additem AllFiles - it will snapshot the directory contents at evaluation time as MSBuild sees it.