msbuild icon indicating copy to clipboard operation
msbuild copied to clipboard

ProjectReference of an executable project : ChildProcess.dll not copied if SelfContained = true

Open jeremyVignelles opened this issue 2 years ago • 4 comments

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?

jeremyVignelles avatar Oct 29 '21 09:10 jeremyVignelles

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 avatar Nov 11 '21 17:11 benvillalobos

@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.

jeremyVignelles avatar Nov 12 '21 14:11 jeremyVignelles

Any update on this ? Did you have a chance to reproduce the issue locally?

jeremyVignelles avatar Mar 02 '22 16:03 jeremyVignelles

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.

benvillalobos avatar Mar 10 '22 00:03 benvillalobos

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 on ProjectReference - 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 on ProjectReference
      • in ResolveProjectReference task, MSBuild task on ChildProcess, MSBuild task is completed on Build target, dll is added to OutputItems, _ResolvedProjectReferecncePaths
      • later on those items are processed in _CopyFilesMarekdCopyLocal, task Copy and copied to published directory of RootProject
    • when no Targets are set to Publish
      • in ResolveProjectReference task, MSBuild task on ChildProcess, MSBuild task has additionally Publish target, there is no OutputItems
      • ChildProcess.exe is copied in GetCopyToOutputDirectoryItems, but dll is never copied.

Let's clarify further steps on next triage.

vlada-shubina avatar Jan 27 '23 12:01 vlada-shubina

@jeremyVignelles could you please answer couple of questions to help us to assess this issue better:

  • is Targets = Publish on ProjectReference intentional?
  • if so, could you please explain your use case?

Thanks

vlada-shubina avatar Jan 31 '23 14:01 vlada-shubina

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

jeremyVignelles avatar Jan 31 '23 14:01 jeremyVignelles

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.

vlada-shubina avatar Jan 31 '23 16:01 vlada-shubina