How do I avoid copying 3rd party C++ dlls? - c#

I have a solution with a C++ project and a c# project, which calls methods from the first one using Interop.
As I want to avoid any hard-coded path, I found a way to set the C++ dll's path in the app.config.
My problem is, that my C++ dll depends on other dlls, which I always have to copy into my bin/Release and bin/Debug folder. How can I avoid this?
It would be nice if I could set the path to the 3rd party dlls in the app.config.
I found this
<probing privatePath="bin\DLLs" />
but it seems to work for application subdirectories only.

Don't hard code location for the DLLs. Put the directories into the %PATH% variable. Assuming Windows as environment read Search path for loading DLLs.
EDIT:
%PATH% is an environment variable, so you can set it with Environment.SetEnvironmentVariables. I would read privatePath from the configuration file, and use the given method to append it to %PATH%. Reading from the configuration file could be done with the ConfigurationManager class.

I will Write folloing command in your post build event (So you need not to do the manual work)
xcopy /s c:\source\your_dll_folder c:\your_target_folder\bin\debug
xcopy /s c:\source\your_dll_folder c:\your_target_folder\bin\Release
Here is post build event location properties of your project

Related

Automatically copying dll.config to a referenced projects output directory

I used the method suggested in the following post to include an App.config file to Class Library project.
Equivalent to 'app.config' for a library (DLL)
It works as mentioned and creates the .dll.config file in respective Class Library projects output directory (e.g. ApiCommunicator\bin\Debug).
I have referenced this Class Library project as a "Project Reference" from another Console Application project within the same Visual Studio solution.
Now the problem is, the .dll is getting copied to the Console Projects output directory (i.e. Engine\bin\Debug) but the .dll.config doesn't. If I manually copy it, everything works fine but is there a way to configure Visual Studio to auto copy .dll.config to any other project's output directory which references the Class Library project?
Thanks,
Bathiya
Although I am late, but my answer can help others. I used the following command as pre-build event:
copy /Y $(SolutionDir)\[YOUR_LIBRARY_PROJECT]\app.config $(ProjectDir)$(OutputPath)[YOUR_LIBRARY_NAME].dll.config
I tried to be dynamic as much as possible, and the above command worked.
I posted the same answer at the question Can we autocopy the *.dll.config? as well.
It would have to be the other way around: Projects referencing your dll could copy it's dll.config from a known location as a post-build event.
However I think it would be much better to provide the configuration from within the consumer application's configuration. That way each referencing project would have an option to adjust the configuration to its needs, which I would think is a critical feature.
If that is not the case, then I don't see the reason for having the .dll.config, and you can just hardcode the values.
You can use the 'Build Events' tab of your project properties to run command line instructions post-build or even pre-build. This way, you can use a simple
copy /Y "<yourconfigfilepath>" "<yourprojectfilepath>\Engine\bin\Debug\"
This will copy the dll.config file you are needing over to the correct directory.

Why my WPF program cannot run without Visual Studio?

I made a WPF program which uses SQLite. And by using Visual Studio 2012, it generates both Debug and Release version exe file. When I go to Debug or Release directory and run my exe file, e.g. MultiStart.exe, it can run normally.
But if I copy the MultiStart.exe to my Desktop and try to run it, it failed.
By several tests, I found that I also need to copy files MultiStart.exe.config and System.Data.SQLite.dll to my Desktop. And then it can run now.
But why? Do we have better solution so that I can make it run without addition files?
Thanks!
Why my WPF program cannot run without Visual Studio?
The question title is not really accurate since it's not really related Visual Studio. MultiStart.exe is dependent on configuration (MultiStart.exe.config) as well as other assemblies (System.Data.SQLite.dll). Without these dependencies the application cannot run (because that is how .NET works).
WPF doesn't necessarily need a config file to run so the question is what is in your config file that the application needs. It might be possible to move this configuration information into the code (e.g. connection string) and remove the app.config but then the values will be hard coded in the application.
In terms of dependent assemblies, instead of deploying them it is possible to embed them as resources and then use the AppDomain.AssemblyResolve Event to read the assembly from a resource (see Embedding assemblies inside another assembly for an example).
Another approach instead of embedding assemblies as resources is to merge them into one assembly. ILMerge is a popular choice for merging assemblies but I read that it can have issues with WPF assemblies (not sure if that applies to you). See Merging dlls into a single .exe with wpf for some other ideas for merging assemblies with WPF.
Note that setting PATH variables does not work because .NET does not use the PATH for resolving assemblies -- see How the Runtime Locates Assemblies for the details.
Another, option instead of copying the MultiStart.exe to the desktop is to use a shortcut on the desktop that links to the appropriate directory. Perhaps that is a simpler solution
You can also use ILMerge to merge all dependencies into single .exe file to simplify distributiuon of your application.
More detaiils on ILMerge can be found here: ILMerge on CodeProject
Example of usage: ilmerge /target:winexe /out:YourDestinationApp.exe
YourCurrentProgram.exe System.Data.SQLite.dll
Better solution that i used to do with my windows form apps is, Copy the entire folder, which contains supporting files. place it where you want. then create a shortcut of your .exe on your desktop. That always worked for me.
Because you are missing some dependency. You can open your config file and set the dependency...but I wouldn't recommend you to change config file manually.
You can also copy the dependent dll in system32 folder. ..but its only a trick because exe first search dlls in current folder than system 32 folder.
Because you're missing things from your PATH. Visual Studio is probably set to copy DLLs to the target directory on build.
You're almost certainly pulling in external libraries. Some of these are part of .NET, while others are packaged in libraries in specific folders. When you start your exe, it looks in your PATH and the current folder for everything (which includes all DLLs Visual Studio copied).
When you moved the exe to the desktop, suddenly it had no idea where those DLLs are. You haven't specifically added them to your PATH, and they are no longer in the current folder. This is why copying those DLLs to your desktop magically made them work.
Unless you stop use SQLite, there is not a way for you to not need that DLL (there are lots of ways to package/reference it though).

Unable to load dll: Module cannot be found

I am using a managed DLL that referencing an unmanaged dll.
I added the unmanaged dll under /External/foo/ directory, and i changed the "Copy To Output Directory" to always.
The problem is that the dlls are copied to the outputDir/External/foo dir and when the runtime tries to find it, it fails with this error: "Unable to load dll: Module cannot be found"
When i copy it directly to the output dir, everything works well.
How can i set the project runtime to search in the sub directories of the outut dir?
Thanks!
You don't want to do this, DLL Search Hell is something you want to avoid. Windows is pretty inflexible about where it looks for DLLs. Rightfully so, DLL Hell is nothing to mess with. The only good place for unmanaged DLLs is in the same directory as your EXE. If you don't want to store the DLLs in the project directory, so copying them is very easy, then you are going to need a post-build event that uses xcopy.exe to copy the DLL to the output directory.
The alternatives are not pretty. If this DLL is implicitly loaded then the only option is to use an installer to add the directory to the system's PATH environment variable. This is a Really Bad idea, way too easy for your program to break. If it is loaded explicitly, either with LoadLibrary or a pinvoke declaration then you have more attractive options since you can alter the search path in your Main() method before the DLL is needed. Either append the path to your local copy of the PATH environment variable by using Environment.SetEnvironmentVariable() or pinvoke SetDllDirectory(). Do beware that you have a deployment problem as well, somebody is going to have to create this subdirectory and copy the DLL there on the user's machine. All great reasons to not do this.
This is something we did in our last project. Write a batch file which copies this unmanaged dll to the output directory. Call the batch file every time the program compiles. You can control the calling of batch file also using a Config key. So it runs based on the config key value true/false. i hope this helps

CSE.exe assembly search while compiling

I am using a batch file with the following commands to successfully compile a C# code on the fly, run the resulting exe and destry the exe.
start /wait C:\WINDOWS\Microsoft.NET\Framework\v3.5\csc.exe /out:PostillionOutgoing.exe PostillionOutgoing.cs /reference:AlexPilotti.FTPS.Client.dll
call SetupCI.bat
start /wait PostillionOutgoing.exe
del PostillionOutgoing.exe
It works exactly the way I wanted. File AlexPilotti.FTPS.Client.dll is present in the same folder as the .cs files are.
The assembly AlexPilotti.FTPS.Client.dll is also needed by a lot of other similar applications. My question is that is there any centralised place where I can keep this DLL so that all the above batch scripts will find it ? By this way I wont have to keep a copy of this DLL in all the separate folders.
I dont want to place the DLL in GAC. I tried in system32 folder also but it didnt work.
You can use the /lib command line to specify search folders for references
see msdn docs here http://msdn.microsoft.com/en-us/library/vstudio/s5bac5fx.aspx
As per the documentation, there is no fixed location that the runtime uses when probing for assemblies (i.e. when it looks into directories because it hasn't been able to locate the assembly already).
However, if your assembly is strongly named then you can use a <codeBase> configuration element in your app.config to direct the runtime to any path of your choosing.
If your assembly isn't strongly named and you don't want to use app.config then unfortunately you are out of options.

Generated .TLB file output directory

I have a compiled c# assembly that I am registering for COM exposure. In order to import my library into some legacy c++ code the .tlb file needs to be in one of my "include" directories.
Instead of adding my bin directory to the include directories of the project that will use it, and since these projects will always be compiled under the same folder structure, I was wondering if, on compile, it was possible to direct my .tlb file to a specific directory.
In the Project Properties under the Build Events there is a Post-build events section. Here you can apply any command you'd like, including copy.
Here's some example code that will copy a file form the bin\Debug directory to another directory in the C:\ drive.
copy "$(TargetDir)\filename.tlb" "C:\output directory path\"
Use XCOPY in a post-build task.

Categories

Resources