I was having what I think is the problem that was originally described. I have a Winform app and a console application as two separate projects, but a single setup project handles both.
Both the Winform app and the console app use the same two external assemblies: one not part of the solution (reference to a file in a folder), and the other from a C# class project (reference to the project).
What I have found is that the installer assumes that the project output is all combined into a single folder on the installation machine. Therefore, all of the common assemblies will also co-reside with the executables that need them. So if you add the project output from the first executable into the folder, that is why you see all its dependencies appear, and then when the second project output is added, only the assemblies not already added will appear.
It doesn't matter if you create subfolders under the Application folder, Visual Studio appears to treat the Application Folder as a whole unit... as far as Project Output (exe, dll and res) are concerned.
There are two ways to solve this. The first is to create a separate installation project for each executable. In a large project, this could be a lot of setup projects.
If you want to keep everything in a single installation, a better option is to use the GAC for the shared assemblies, which is described in another Stack Overflow article here: Use Visual Studio Setup Project to automatically register and GAC a COM Interop DLL
MSI can get the job done. Right-click "File System on Target Machine",
Add, GAC. Right-click that added folder, Add, Project Output. That
ensures the assembly is gac-ed.
The GAC is the better solution in my mind, because your assemblies are managed by the .NET layer if you later make changes and enhancements to them. One of the benefits of .NET is to eliminate the old "DLL hell" issues that were in Win 98 and previous versions of Windows. I highly recommend using it for your common code.