views:

74

answers:

3

I have C# wrapper code that calls functions from a native (C++) dll. Currently, I can add a reference to the C# dll and have set the 'Copy Local' option to true. However the native dll, which is a dependency, cannot be added as a reference - so there is no 'Copy Local' option.

I have tried the following approaches

  1. Using a post-build events to copy the native dll from the Libs folder to the $(TargetFolder)

    copy "$(ProjectDir)Libs\NQuantLibc.dll" "$(TargetDir)NQuantLibc.dll"

  2. Included the native dll as an existing item in the project (Add -> Existing Item -> Include dll). This option allows me to use the 'Copy Local' option. The downside to this approach is that the dll always shows as a project item.

I also tried "Show All Files" which allowed me to see the Libs folder. I then include the NQuantLibc.dll file in the project which allowed me to set the 'Copy Local' option. However, this gave me a unexpected result. It created a Libs subfolder containing the dll within the bin folder (eg bin/debug/Libs/NQuantLibc.dll). Not ideal since the C# dll was not able to properly call the native dll since it was not there.

Both of the above options above work. Are there any better ways to copy a native dll to the bin folder such that the dependency will always be resolved? Alternatively, is there a different approach to this type of scenario?

A: 

Add the dll as a file in the project ("As link" maybe if u still want it to reside in another directory). Then set the Build Action to content and Copy to output directory to true.

AZ
Does this apply to VS 2010 Express? I can't seem to find the 'Add link' option. The remainder of the answers seems very similar to what was described in point 2. Am i mistaken?
Ahmad
@Ahmad you can add the file as link by pressing on the little downward arrow on the "Add" button (from Add → Existing item...), and selecting `Add as Link`
hmemcpy
@hmemcpy - does not seem to work. Dll is not being copied to the bin folder and a corresponding exception is being thrown.
Ahmad
Actually it is being copied but to a Libs subfolder
Ahmad
+1  A: 

If you're OK with the created "Libs" folder, you can try adding it to the probing path for your application, by adding the following in the app.config file:

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="Libs;Bin2"/>
      </assemblyBinding>
   </runtime>
</configuration>

This will cause the runtime to look in all the specified directories for the DLL.

EDIT Unfortunately, this does not impact the unmanaged DLL loading by DllImport.

hmemcpy
I was busy on SO trying to find out why the exception was being thrown :(. Thanks though.
Ahmad
+2  A: 

Use Project + Add Existing Item and select the DLL. Select the added file in the Solution Explorer window. In the Properties window, change the Copy to Output Directory setting to "Copy if newer".

Hans Passant
+1 Easy and pain-free solution
Christian
I have done that as one possible option - see point 2
Ahmad
I don't get the problem, it *is* a project item. It won't run without it, just as it won't run when a source code file is missing.
Hans Passant
@hans - i'm not saying there is a problem. I am only looking for a better way. There is one issue that I think is of concern. When adding the DLL as an existing item, a copy of the DLL is created in your project folder, thus if your original DLL ever gets updated, you will need to re-add it to the project. The post-build copy command in this case will be more robust IMO.
Ahmad
No it doesn't. Note my advice: "Copy if newer".
Hans Passant
@hans - tried that using a simple text file. Created `test.txt` with text "v1" in the Libs folder. Added the item to the project using the method described. A copy is created in the main project folder. Built the project and `test.txt` is copied to the bin folder as expected. Now I modified the contents of `test.txt` in the Lib folder and rebuilt. The file in the bin folder is still the old version. Am I misunderstanding something?
Ahmad
Take a double-barreled shutgun and aim it between the disk platters. Pull. Problem solved. This works on everybody's machine. Good luck.
Hans Passant
@hans - haha, I leave mine at the office. But seriously, if I'm being an idiot, I would appreciate clarification so I can learn from my mistakes.
Ahmad