msbuild
msbuild copied to clipboard
ProjectReference of an executable project : ChildProcess.dll not copied if SelfContained = true
Issue Description
I have two projects : RootProject
and ChildProcess
. Both are executables, and RootProject
starts ChildProcess.exe
as part of its work.
When I want to publish the RootProject
with a self-contained deployment (dotnet publish -r win-x64
), the ChildProcess.exe
is correctly put into the output folder, but not ChildProcess.dll
.
I'm using this to reference the project:
https://github.com/jeremyVignelles/ReproProjectReferences/blob/4260b1e29dfd50e78f101ca759212bb7ff1be99a/RootProject/RootProject.csproj#L8
I had issues referencing the project, because if I don't set the RuntimeIdentifier, the command dotnet publish -r win-x64
fails with the error:
C:\Program Files\dotnet\sdk\5.0.402\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.targets(993,5): error NETSDK1150: le projet référencé « ..\ChildProcess\ChildProcess.csproj » est un exécutable qui n'est pas autonome. Un exécutable non autonome ne peut pas être référencé par un exécutable autonome. [D:\Projects\Tests\TestProjectReferences\RootProject\RootProject.csproj]
I got the workaround idea from this issue : https://github.com/dotnet/sdk/issues/10625#issuecomment-697646664 : set a "default" rid in the csporj.
Given the message, I suppose that referencing executables is a valid scenario to reference an executable this way, but I was unable to find any document mentionning this, all I'm doing is trial and error.
Steps to Reproduce
- clone https://github.com/jeremyVignelles/ReproProjectReferences
- run one of these tests :
-
dotnet run -p RootProject/RootProject.csproj
-
dotnet run -r win-x64 -p RootProject/RootProject.csproj
- Open Visual Studio and run the
RootProject
-
dotnet publish -r win-x64 RootProject/RootProject.csproj && RootProject/bin/Debug/net5.0/win-x64/publish/RootProject.exe
-
Expected Behavior
Hello world
should be displayed in all cases
Actual Behavior
It works fine with Visual Studio (the dll is copied), but I get an error from ChildProcess.exe
in all other cases:
The application to execute does not exist: 'D:\Projects\Tests\TestProjectReferences\RootProject\bin\Debug\net5.0\win-x64\ChildProcess.dll'.
Indeed, there is no such file in the output folder.
Workaround
I created a workaround branch, to edit the RootProject.csproj, that you can see here : https://github.com/jeremyVignelles/ReproProjectReferences/blob/workaround/RootProject/RootProject.csproj
Basically, I'm referencing the .dll I need in a <None
, after the references have been resolved. It seems however, that Visual Studio doesn't create the ChildProcess\bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\
folder, but can successfully copy the .dll in the output folder.
Environment
.NET SDK 5.0.402 VS 2019 (16.11.0)
Ask us questions
Why is the .dll file not copied in the first place, when I run it from the CLI ? Am I missing something?
Why doesn't VS create the publish folder, and how come does it copy the dll files that are not copied by the dotnet CLI?
Team Triage: It looks like you have ReferenceOutputAssembly="false"
set on your project reference. This prevents the output of your projectreference from being copied over. If you remove that, does it successfully copy over the .dll
?
https://docs.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-items?#projectreference
@BenVillalobos : Thanks for your reply.
I just moved to VS2022 and .net 6 , and it seems to be still failing with dotnet run --project RootProject/RootProject.csproj
.
I tried your suggestion about removing ReferenceOutputAssembly
(see here ) but that didn't change anything, the dll is still not copied.
As far as I understand the ReferenceOutputAssembly
property tells the compiler that all types from the ChildProcess are now available to be called from the RootProject, which effectively leaks types. I don't want that behavior, as the two processes are independent and only communicate through IPC.
Any update on this ? Did you have a chance to reproduce the issue locally?
It does repro. I suspect it's because ChildProcess builds using the Publish target. This probably leads to that .dll
not being included somewhere down the chain (which sounds odd)
The workaround you have is the one I would have suggested, I'll bring this up in bug triage tomorrow, there may be another way to accomplish this.
Notes from the investigations:
- the issue is still reproduced on the repro project mentioned in the issue description
- the issue is not reproduced when
Targets = "Publish"
is not set onProjectReference
- the mentioned commands are executed as expected, https://github.com/jeremyVignelles/ReproProjectReferences/blob/a101e48708874e455b6c4cd5ea21f3190fd5c94b/RootProject/RootProject.csproj#L8 - the difference in behavior is
- when no
Targets
are set onProjectReference
- in
ResolveProjectReference
task,MSBuild
task on ChildProcess,MSBuild
task is completed onBuild
target, dll is added toOutputItems
,_ResolvedProjectReferecncePaths
- later on those items are processed in
_CopyFilesMarekdCopyLocal
, taskCopy
and copied to published directory ofRootProject
- in
- when no
Targets
are set toPublish
- in
ResolveProjectReference
task,MSBuild
task on ChildProcess,MSBuild
task has additionallyPublish
target, there is noOutputItems
-
ChildProcess.exe
is copied inGetCopyToOutputDirectoryItems
, butdll
is never copied.
- in
- when no
Let's clarify further steps on next triage.
@jeremyVignelles could you please answer couple of questions to help us to assess this issue better:
- is
Targets = Publish
onProjectReference
intentional? - if so, could you please explain your use case?
Thanks
It's been a year and l'm not working for the same company anymore, so I can't be sure.
The idea was that I wanted an exe file I could call from the parent process. Presumably, If I didn't set that target, the .exe file was never generated, and the dll was referenced as a dll rather than an executable.
I really needed an executable I could spawn for my use case
Thank you for quick reply.
This use case sounds reasonable but after test on both .NET SDK 5.0.4xx and current .NET SDK 7.0.1xx, the executable is created during Build
so specifying Targets=Publish
is not needed, and the given cases are works as expected.
I created https://github.com/dotnet/msbuild/issues/8376, so we can document this use case better.
I'm closing this issue, please feel free to comment if you need to reopen it.