No executable found matching command "dotnet-/app/Build\ClearPluginAssemblies.dll" Docker - c#

I'm trying to run my ASP.NET Core 2.1 application with docker image. For that I have docker file with the following content:
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY . .
RUN dotnet restore
# copy everything else and build app
COPY Presentation/MyProject.Web/. ./Presentation/MyProject.Web/
WORKDIR /app/Presentation/MyProject.Web
RUN dotnet publish -c Release -o out
# Build runtime image
FROM microsoft/dotnet:aspnetcore-runtime
WORKDIR /app
COPY --from=build /app/Presentation/MyProject.Web/out .
ENTRYPOINT ["dotnet", "MyProject.Web.dll"]
But when execute the command docker build -t MyProject-web . it gives me an error:
The command '/bin/sh -c dotnet publish -c Release -o out' returned a non-zero code: 1
MyProject.Web -> /app/Presentation/MyProject.Web/bin/Release/netcoreapp2.1/MyProject.Web.dll
No executable found matching command "dotnet-/app/Build\ClearPluginAssemblies.dll"
/app/Build/ClearPluginAssemblies.proj(21,5): error MSB3073: The command "dotnet "/app/Build\ClearPluginAssemblies.dll" "OutputPath=/app/Build/../Presentation/MyProject.Web/bin/Release/netcoreapp2.1/|PluginPath=/app/Presentation/MyProject.Web/Plugins/DiscountRules.CustomerRoles/;/app/Presentation/MyProject.Web/Plugins/ExchangeRate.EcbExchange/;/app/Presentation/MyProject.Web/Plugins/ExternalAuth.Facebook/;/app/Presentation/MyProject.Web/Plugins/Payments.CheckMoneyOrder/;/app/Presentation/MyProject.Web/Plugins/Payments.Manual/;/app/Presentation/MyProject.Web/Plugins/Payments.PayPalStandard/;/app/Presentation/MyProject.Web/Plugins/Payments.Square/;/app/Presentation/MyProject.Web/Plugins/Payments.Worldpay/;/app/Presentation/MyProject.Web/Plugins/Pickup.PickupInStore/;/app/Presentation/MyProject.Web/Plugins/Shipping.FixedByWeightByTotal/;/app/Presentation/MyProject.Web/Plugins/Shipping.UPS/;/app/Presentation/MyProject.Web/Plugins/Tax.FixedOrByCountryStateZip/;/app/Presentation/MyProject.Web/Plugins/Widgets.GoogleAnalytics/;/app/Presentation/MyProject.Web/Plugins/Widgets.NivoSlider/|SaveLocalesFolders="" exited with code 1.
The command '/bin/sh -c dotnet publish -c Release -o out' returned a non-zero code: 1
Edit 1:
Here is my project structure:
Build
ClearPluginAssemblies
Libraries
MyProject.Core
MyProject.Data
MyProject.Services
Plugins
MyProject.Plugin.Discount
MyProject.Plugin.Payment
..
Presentation
MyProject.Web
MyProject.Web.Framework
Tests
Edit:2 Web project file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<Description>MyProject.Web is also an MVC web application project, a presentation layer for public store and admin area.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Libraries\MyProject.Core\MyProject.Core.csproj" />
<ProjectReference Include="..\..\Libraries\MyProject.Data\MyProject.Data.csproj" />
<ProjectReference Include="..\..\Libraries\MyProject.Services\MyProject.Services.csproj" />
<ProjectReference Include="..\MyProject.Web.Framework\MyProject.Web.Framework.csproj" />
</ItemGroup>
<ItemGroup>
<!-- We copy the entire \App_Data directory. But we ignore JSON files and data protection keys -->
<Content Include="App_Data\**" CopyToPublishDirectory="PreserveNewest" Exclude="App_Data\*.json" />
<Content Update="App_Data\*.json" CopyToPublishDirectory="Never" />
<Content Update="App_Data\DataProtectionKeys\*.xml" CopyToPublishDirectory="Never" />
<Compile Remove="Plugins\**" />
<EmbeddedResource Remove="Plugins\**" />
<None Remove="Plugins\**" />
<Content Include="Plugins\**" CopyToPublishDirectory="PreserveNewest" Exclude="Plugins\**\*.config;Plugins\**\*.cshtml;Plugins\**\*.json" />
<Content Include="Themes\**" CopyToPublishDirectory="PreserveNewest" Exclude="Themes\**\*.config;Themes\**\*.cshtml;Themes\**\*.json" />
<!-- We copy the \Logs directory -->
<Content Include="Logs\**" CopyToPublishDirectory="PreserveNewest" />
<None Update="Areas\Admin\sitemap.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Plugins\" />
</ItemGroup>
<!-- This target execute after "Build" target.
We use it to clean up folder with plugins from unnecessary and obsolete libraries. -->
<Target Name="NopTarget" AfterTargets="Build">
<ItemGroup>
<!-- Get plugin description files to get plugin paths -->
<PluginsDescription Include="$(MSBuildProjectDirectory)\Plugins\**\plugin.json;" />
<!-- Get paths for all plugins -->
<PluginsFolders Include="#(PluginsDescription->'%(relativedir)')" />
<!-- Get all the libraries from the shadow copy folder to remove them,
because depending on the settings, this may not happen when the application is starting,
but this can lead to unpredictable results during debugging of the project. -->
<ShadowCopiesLibraries Include="$(MSBuildProjectDirectory)\Plugins\bin\*.*" Exclude="$(MSBuildProjectDirectory)\Plugins\bin\placeholder.txt" />
</ItemGroup>
<PropertyGroup>
<PluginsFolders>#(PluginsFolders)</PluginsFolders>
</PropertyGroup>
<!-- Delete libraries from the shadow copy folder -->
<Delete Files="#(ShadowCopiesLibraries)" />
<!-- When .NET Core builds a project, it copies all referenced libraries to the output folder.
For plugins it creates too many unnecessary files that just take up space.
At the moment you can't disable this behavior. That's why we have to manually delete all unnecessary libraries from plugin output directories. -->
<MSBuild Projects="$(MSBuildProjectDirectory)\..\..\Build\ClearPluginAssemblies.proj" Properties="PluginPath=$(PluginsFolders)" Targets="NopClear" />
</Target>
<PropertyGroup>
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>
</PropertyGroup>
</Project>

This looks more like a dotnet publish issue then an actually issue with docker.
If you search on the actual error that dotnet cli shows MSB3073, you can find that it's often related to post build events.
In many cases, the path to each folder/assembly referenced in the post build event is not correct.
If we look closer at where we are when the publish command is executed
WORKDIR /app/Presentation/MyProject.Web
And then for example look at the PluginPath in the error message
..PluginPath=/app/Presentation/MyProject.Web/Plugins/DiscountRules.CustomerRoles/;..
You can then see that the path is not inline from where the command is executed.
One solutions would be to add absolute path or make them relative from where the publish command is executed. You could also specify a specific post/pre-events for each configuration, here's an answer regarding publish-events

Related

.Net 5 Publish Single File - Produces exe and dlls

I am using VS 2019 and .Net 5 to build a simple console application. I wanted to share this app with a friend so I tried to publish it as a single file but I keep getting some extra DLLs that the executable needs to run correctly.
Edit: Switching this project to .net core 3.1 works as expected I am able to export a single Exe file without any required DLLs.
Dotnet Cli:
dotnet publish -c Release -o publish -p:PublishReadyToRun=true -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
Csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<PublishSingleFile>true</PublishSingleFile>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.28" />
</ItemGroup>
</Project>
Its known issue that described here: https://github.com/dotnet/runtime/issues/36590
And new dev experience provided here: https://github.com/dotnet/designs/blob/main/accepted/2020/single-file/design.md#user-experience
So in your case you need use p:IncludeNativeLibrariesForSelfExtract=true additionaly.
Full command:
dotnet publish -c Release -o publish -p:PublishReadyToRun=true -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true -p:IncludeNativeLibrariesForSelfExtract=true
or include this flag in .csproj file
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<PublishSingleFile>true</PublishSingleFile>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PlatformTarget>x64</PlatformTarget>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>

Running in "No report files specified" when trying to generate test coverage in docker pipeline (Linux)

I use a linux-based docker pipeline to build and do automatic testing with the NUnit Framework in a C#-.NET-Core based solution.
"Test" job in my .gitlab-ci.yml-File:
runTests:
stage: test
image: docker-registry.xyz.de/${CI_PROJECT_PATH}/build:${CI_COMMIT_REF_SLUG}_backend_${CI_COMMIT_SHA}
services:
- name: atsnngs/mysql-aurora-compatible
alias: mysql_test
tags:
- docker
- linux
- shared
variables:
GIT_STRATEGY: none
artifacts:
expire_in: 30m
paths:
- $CI_PROJECT_DIR/pages
script:
- mkdir $CI_PROJECT_DIR/pages
- mkdir mkdir /tmp/pages
- cd /app
- nohup dotnet run --project ./ServiceLoader/ServiceLoader.csproj Test > dotnetcore.log &
- sleep 10s && dotnet test -v normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude=[NUnit3.TestAdapter]*
- reportgenerator -reports:/app/Tests/coverage.opencover.xml -targetdir:/tmp/pages
- ls -l /tmp/pages
- mv /tmp/pages/index.htm /tmp/pages/index.html
- mv /tmp/pages $CI_PROJECT_DIR/
dependencies:
- build
In the Dockerfile, which I use to build the image I am using to execute testing, I install the report generation tool (For readability reasons I skipped the dotnet restore and build parts of the Dockerfile):
FROM microsoft/dotnet:2.1-sdk AS build
# install reportgenerator
RUN dotnet tool install --global dotnet-reportgenerator-globaltool
ENV PATH /root/.dotnet/tools:$PATH
But when I ran the pipeline the report generation fails:
$ reportgenerator -reports:/app/Tests/coverage.opencover.xml -targetdir:/tmp/pages
No report files specified.
I have already compared the Dockerfile and .gitlab-ci.yml file with another project I used this approach and could not find any difference which could explain this error. Is there any other place where I need to have a look at?
Any help is highly appreciated!
The problem is solved through adding the Nuget packages for coverlet.msbuild and dotnet-reportgenerator-cli. These packages are missing and lead to the error in the report generation.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsTestProject>true</IsTestProject>
<IsPackable>false</IsPackable>
...
</PropertyGroup>
<ItemGroup>
...
<PackageReference Include="Nunit" Version="3.11.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="coverlet.msbuild" Version="2.4.0" />
<PackageReference Include="dotnet-reportgenerator-cli" Version="4.0.5-rc2" />
</ItemGroup>
</Project>
In my case, I had multiple defined in the csproj file. Removing „net48“ and other legacy .NET framework TFMs helped in my case.

VS Code: How to copy files to output directory depending on build configurations

I just started a new project in VS Code (C#, .NET Core). Anyways, I want to be able to copy files from within my project directory to the output directory like I can in visual studio. But I also want to copy specific files depending on whether or not I'm building for 32 or 64 bit.
I've looked around but so far all I've learnt how to do is copy files regardless of my build configurations.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'win-x86' Or '$(RuntimeIdentifier)' == 'win-x64'">
<None Update="foo.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'win-x64'">
<None Update="foo.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Steps:
Create a console app by running dotnet new console
Add foo.txt and foo.xml to the project folder.
Edit the .csproj file as above.
Build the project with multiple configurations.
dotnet build -c Release -r win-x86
foo.xml is copied only for a x-64 build whereas foo.txt is copied for both RID's

The command " run C:\agent\_work\8\s\Web\webapi.nswag" exited with code 9009

I'm trying to build a project with NSwagger installed.
Here is my .csporj configuration:
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\NSwag.MSBuild.11.15.3\build\NSwag.MSBuild.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NSwag.MSBuild.11.15.3\build\NSwag.MSBuild.props'))" />
</Target>
<Target Name="BeforeBuild">
<Exec Command="$(NSwagExe) run $(SolutionDir)webapi.nswag" />
</Target>
Error :
ValidateSolutionConfiguration:
Building solution configuration "Debug|Any CPU".
Project "C:\agent_work\8\s\Web\CSU.Marketplace.Web.sln" (1) is building "C:\agent_work\8\s\Web\CSU.Marketplace.Web\CSU.Marketplace.Web.csproj" (2) on node 1 (default targets).
BeforeBuild:
run C:\agent_work\8\s\Web\webapi.nswag
'run' is not recognized as an internal or external command,
operable program or batch file.
Web\CSU.Marketplace.Web\CSU.Marketplace.Web.csproj(942,5): Error MSB3073: The command " run C:\agent_work\8\s\Web\webapi.nswag" exited with code 9009.
The project file does not import the NSwag build tasks.
Therefore at build time, $(NSwagExe) expands to an empty string, and msbuild tries to run the rest of the command:
run C:\agent_work\8\s\Web\webapi.nswag
Add something like this:
<ItemGroup>
<PackageReference Include="NSwag.MSBuild" Version="11.12.9" />
</ItemGroup>

Why does my MSBuild Exec Command Fail?

I have a pretty simple setup for this application I'm using to test something:
-Solution in VS
-Project for cs code (named Client)
-Project for Thrift files( named Thrift)
-Folder for Erlang Code(Doesn't show up in VS)
The idea is I'll build the Thrift project, have it generate the code for both languages, copy the generated erlang code to the correct directory (with MSBuild, but first things first), and include the generated csharp code in the Thrift project. To do this I have the following "BeforeBuild" target:
<Target Name="BeforeBuild">
<Exec Command="cmd /c "C:\Windows\System32\thrift.exe" -gen erl -gen csharp *.thrift" />
<ItemGroup>
<CSFile Include="$(SolutionDir)gen-csharp\*" />
</ItemGroup>
I get the error "'C:\Windows\System32\thrift.exe' is not recognized as an internal or external command, operable program or batch file".
I tried Command="thrift ..." since thrift is in my PATH, but found out that MSBuild doesn't find programs from the PATH variable.
Note: Using the command without "cmd /c" results in the same error message, but with a different error code (9001, because MSBuild is unable to find the file, instead of "cmd /c" failing to find the file).
Edit: For posterity, the working result is:
<Project>
...
(Auto generated data)
...
<PropertyGroup>
<CleanDependsOn>
$(CleanDependsOn);
CleanThriftGen;
</CleanDependsOn>
<ErlangProjectSrcDir>$(SolutionDir)Server\src\gen\</ErlangProjectSrcDir>
<GenCSharpDir>gen-csharp\</GenCSharpDir>
<GenErlDir>gen-erl\</GenErlDir>
<ThriftDir>C:\thrift\</ThriftDir>
</PropertyGroup>
<Target Name="BeforeBuild">
<Exec Command="$(ThriftDir)thrift.exe -gen erl -gen csharp *.thrift" />
</Target>
<Target Name="AfterBuild">
<ItemGroup>
<ErlangSrcGroup Include="$(GenErlDir)**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(ErlangSrcGroup)" DestinationFiles="$(ErlangProjectSrcDir)%(RecursiveDir)%(Filename)%(Extension)" ContinueOnError="false" />
</Target>
<Target Name="CleanThriftGen">
<RemoveDir Directories="$(ErlangProjectSrcDir)" />
<RemoveDir Directories="$(GenCSharpDir)" />
<RemoveDir Directories="$(GenErlDir)" />
</Target>
<ItemGroup>
<CSharpGenGroup Include="$(GenCSharpDir)**\*.*" />
</ItemGroup>
Found the majority of my answer, in my haste I had stuck the executable in the first directory I knew would already be in my path, System32. Moving it to another folder fixes the error when running the tool directly from VS (vs cmd /c).
But I'm still not clear on what caused this. I don't know why cmd /c would be unable to find it when a command prompt with normal privileges could, and I don't know why VS couldn't find it.
As a test I gave the new folder I placed it in permissions to require administrative privileges to write to, same as System32, but VS is still able to run it from there.

Categories