How do I add a reference to an unmanaged C++ project called by a C# project?

One solution (the.sln)

One C++ project (mycppproject.vcxproj in 2010or mycppproject.vcproj in 2008) which compiles a native DLL exporting some function(s). In debug this builds c:\output\Debug\mycppproject_d.dll and in release this builds c:\output\Release\mycppproject.dll.

One C# console application (mycsharpconsole.csproj) containing PInvoke calls into the DLL.

All compiles fine.

When I build, I would like to be able to add a reference from the csharp project to the cpp DLL project so that it can copy the appropriate file from the appropriate directory into the \bin\Debug directory the csharp project is built into.

This should be possible, since the IDE knows everything there is to know about where the DLL gets built, and where the C# application gets built.

In Visual Studio 2010:

I've tried "Dependencies..." on the csharp project and adding a dependency on mycppproject, but that has no effect.

I've tried "Add Reference..." on the csharp project and adding a reference to the cpp project, but I get a warning message 'The Target Framework version for the project "mycppproject" is higher than the current project Target Framework version. Would you like to add this reference to your project anyway?' (Yes/No/Cancel).

Clicking "Yes" produces the error message "A reference to mycppproject" could not be added."

Answers


Visual Studio doesn't support referencing an unmanaged C++ project from a managed C# one, but MSBuild supports referencing any project from any other project.

You can manually add a reference to your project by editing the .csproj file by hand. In the file, find your existing set of ProjectReference elements (or add a new ItemGroup if you don't have one) and add the following reference:

<ProjectReference Include="..\mycpproject.csproj">
  <Project>{b402782f-de0a-41fa-b364-60612a786fb2}</Project>
  <Name>mycppproject</Name>
  <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
  <OutputItemType>Content</OutputItemType>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</ProjectReference>

When you perform the build, the reference will cause MSBuild to build the referenced project first. The ReferenceOutputAssembly value tells MSBuild not to copy the output assembly of the build (since the C++ project does not produce one), but the OutputItemType and CopyToOutputDirectory values instruct it to copy the output content to the referencing project's output folder.

You will be able to see the reference in Visual Studio, but you can't do much with it there.

This answer is based on a similar problem solved by Kirill Osenkov on his MSDN blog: https://blogs.msdn.microsoft.com/kirillosenkov/2015/04/04/how-to-have-a-project-reference-without-referencing-the-actual-binary/


You cannot add a reference to an unmanaged DLL.

Instead, you should make a post-build task to copy the file.

Alternatively, you can add a link to the unmanaged DLL as a file in the C# project, and set Build Action to None and Copy to Output Directory to Copy If Newer.


I would follow Slaks' second answer...

[...] you can add a link to the unmanaged DLL as a file in the C# project, and set Build Action to None and Copy to Output Directory to Copy If Newer.

... followed by my comment, to differentiate between Debug and Release builds (even if is a little bit "hackish", since it requires you to manually edit the C# project file)

open your C# project's csproj file with a text editor and search for all "YourNativeCppProject.dll" occurrences (without the ".dll" subfix, so if you added pdb files as a link too, you'll find more than one occurrence), and change the Include path using macros, for example: Include="$(SolutionDir)$(ConfigurationName)\YourNativeCppProject.dll

PS: if you look at the properties (F4), VS shows you the Debug's path even if you switch to the Release configuration, but if you compile, you'll see that the dll copied to output is the release version*


Add Rederences only works for .NET assemblies, .net projects in the same solution or for COM components ( for which a manager wrapper will be created anyway... ).

the fact that in your C# code you access the C++ dll with DLLImport does not mean that Visual Studio will know from where to where the external dll should be copied.

Imagine that DLLImport is a runtime option, the path you puth in there is used at runtime to look for the dll, so you have to deploy the c++ dll yourself and make it available for the .net application, usually in the same bin folder.


Need Your Help

Adding Navigation Bar programmatically iOS

ios objective-c iphone swift xcode

I am trying to make an App with a Navigation Bar (Back button, title, etc) and a Tab Bar (Toolbar on the bottom). I am using subviews so I don't have to worry about the status bar, navigation bar, ...

Hibernate/persistence without @Id

java hibernate primary-key hibernate-annotations

I have a database view that yields a result set that has no true primary key. I want to use Hibernate/Persistence to map this result set onto Java objects. Of course, because there is no PK, I cannot