windows service Can't call C++ Native Methods [DllImpor("myDLL")] - c#

I tried to use this way:
DLLImport a variable MFC dll
It works.
The problem is the C++ dll "myDLL" needs another DLL "XDLL",
I found that
the service current fodler when services started is the system32, not where the assemble are !!!
In this case, if I put "XDLL" in system32 it would work...
What I need is away to run it without copying anything to System32 or anyway else
Is it C# windows service issue ? or C++ ? what should I do ?
Thanks

If DLLs are specified by name only, that is without a complete path, then the Dynamic-Link Library Search Order comes into play.
There are lots of ifs and buts with this, but the bottom line is that if you put all the DLLs that your executable needs in the same directory as the executable, then the loader will be able to find the DLLs. That is the best practice because it requires no configuration, and you can be certain of which version of the DLL is to be loaded.

Related

How to call tool DLLs in C# when the DLL-path is different on the target PC?

I might be a bit stupid, but I want to create a tool in Visual Studio in C# and want to call third party tools via their API-DLLs. The only topics I found here are dealing with one of the two methods that I already know:
Compilation time: add a reference to "C:\FooTool\foo.dll" in my project + "using fooToolNamespace.fooToolClass" in my code (compilation time) --> I can "naturally" use the classes of the DLL and will even get full IntelliSense support if a suiting XML-file is available with the DLL. Also compilation time checks will be done for my usage of the dll.
Dynamic (run time): calling e.g. Assembly.LoadFile(#"C:\FooTool\foo.dll") and then using reflection on it to find functions, fields and so on --> no IntelliSense, no compilation time checks
So I actually have the DLL at hand and thus option 1) would be nice during development. But if my tool is used on a different PC, the third-party DLL might be in a different path there, e.g. "C:\foo\foo.dll" and "C:\bar\foo.dll".
In my understanding using a copy of "foo.dll" will not work, because "foo.dll" might have dependencies, e.g. requiring other files of the FooTool-directory. Thus in my understanding I have to call the DLL which is "installed" to the target PC and not a local copy of it.
So can I somehow change the path where my tool accesses the "foo.dll" at runtime and still use method 1) during development?
Or is there another way of doing things?
Or am I just dumb and there is a simple solution for all this?
Thanks a lot for the help and have a great day
Janis
To be able to use option 1 (a referenced DLL), you need to put the DLL somewhere "where your EXE (or, more precisely, the Assembly Resolver) can find it" on the customer's PC.
So where does the assembly resolver look for your DLL?
In the directory where the EXE resides (for desktop/console applications) or the bin subdirectory (for web applications). Since you mention that your DLL requires other dependencies as well, you'd need to copy them to that location as well.
The Global Assembly Cache (GAC). If your dependency supports this, installing it to the GAC ensures that it can be found by your application.
These two are the "supported" scenarios. There is also the possibility to tweak the assembly resolver to look into other directories as well, but that should be reserved for special cases where the other two options failed. (We had such a case and solved it with a custom AssemblyResolve handler on the application domain.)

dll not found (non COM object)

I made an application in vs2010 (.net 4.0). I published it, both using publisher and InstallShield LE.
But when I run application, I get error that a dll is not found. I know which dll is missing. This is a non-COM object and I can't add it to my project in vs2010. I am using a wrapper library which invokes this dll.
If I paste that dll in syswow64, my application works fine. But I want a cleaner way of doing it. I already had a look at Hans's answer here. But I have no clue what is side-by-side cache.
Adding path to environment variables works fine too.
I am not sure if updating registry and adding a path value will work or not. I would like to know if I can update registry for my application and direct the path where it searches for particular dlls.
Thanks.
Modifying the user's PATH variable is a very heavyweight solution, and you should avoid that. Likewise, do not put the DLL in the system directory. That belongs to the system and is private to you.
The recommended way to solve the problem is simply to put the DLL in the same directory as the executable. The directory in which the executable lives is searched first when the loaded tries to locate DLLs. It is the safest place to put your native DLLs.
If for some reason you cannot put the DLL in the executable directory, there are other options:
Call SetDllDirectory with the directory of your DLL before making your first p/invoke call. When that call returns, call SetDllDirectory passing NULL to restore the default DLL search order.
Make an explicit call to LoadLibrary with the full path of your DLL before making your first p/invoke call. Once the DLL has been loaded, future p/invoke calls will use the module that has been loaded.
If you know the DLL name in advance, there is a simple way.
You can simply use LoadLibrary to load the DLL from its known location (based on for example a configuration file entry).
As long as you successfully call LoadLibrary before any of the DLL methods are used, this will succeed as the DLL is already loaded.
This works because you can LoadLibrary with a full path, and once that is done, subsequent calls to LoadLibrary with just the filename will succeed immediately, since the library is already loaded.

Launching C# WPF from Java causes FileNotFoundExceptions

I have a existing Java Project which needs functionality from a SDK written in C#. It should open a WPF Window and send the information back to Java on close.
For a basic connection of those two worlds i created a Java Project ("DotNetCaller") calling native functions. These are implemented in a C++/CLI Project ("DotNetBridge") which calls the C# Project ("DotNetApplication").
I already can set Strings from Java in C# and callback from C# to Java.
But as soon as i add a WPF Window and try to launch it with:
Application app = new Application();
app.Run(new DotNetWindow());
in a STA Thread it crashes.
The DotNetApplication doesnt find mscorlib.resources, after i provide the DLL, PresentationFramework.resources is missing and if i provide that, the DotNetApplication.resource is missing (which i cant provide).
If i call the DotNetApplication alone or from the DotNetBridge the Window displays as expected.
Can anyone tell ma what i'm really missing here?
Thanks
Edit:
I looked at this example once more and tried to adapt it to my needs.
I have set the dll directory of the ResolveEventHandler to the .NET dir in "Referenced Assemblies"
C:\Program Files (x86)\Reference
Assemblies\Microsoft\Framework.NETFramework\v4.0
and added a Window in C#.
It failed aswell but with a new exception in the C++ part rather than C#.
The ResolveHandler gets called with an empty argument causing an uncatchable exception in mscorelib.
I added a check if the String is empty and this basic approach works fine now.
I'm still unsure if i have the correct approach for this, so feel free to contribute.
Your AppDomain::AssemblyResolve handler probably needs to be overhauled and based on your own understanding of what you want to do. There is some guidance here. The basic rule is that you return nullptr for requests that you can't handle.
But first you have to plan the locations in which you want to deploy (and/or debug) your assemblies. A simple layout would be to put all of the assemblies that your JNI DLL depends on in the same folder as the JNI DLL (with the exception of any that will be installed in the GAC). You can then use its location to satisfy resolution requests. But remember to return nullptr if no file containing a manifest for an assembly with the requested name is present there. (This is likely the case with your ".resources" requests. If there isn't one it's okay unless you know otherwise.)
I'd be a little surprised if an assembly in a Reference Assemblies folder wasn't also in the GAC—but it'd be up to the assembly provider. Reference Assemblies is for design and build tools (e.g. Visual Studio). (The old way was for each folder that had assemblies in it to be registered for each version of Visual Studio so the assemblies could be used for design and build.) If a dependency is not in the GAC, you can use the "Copy Local" property on the reference to make it available for debugging.
You might find the Assembly Binding Log Viewer useful while designing and troubleshooting. With it you can see all the folders and extensions that are tried before giving over to calling the AppDomain::AssemblyResolve handler chain. (Disable logging when you are done.)

iis7 hosted wcf service : avoid placing dll in system32 folder

I have a wcf service referencing a dll. Only way it works is by placing the dll in %windir%/system32 folder.
Things I have tried
tried switching between iis express, development server and iis (but this is irrelevant)
placing the dll in the bin folder and/or other application folders
trying to use the "regsvr32" util but the dll is not a com dll so it does not work.(no ddl entry point)
It is not a .NET dll so I don't think GAC can be manipulated to work with this
played with the system path variable without any success
What I actually want
A simpler method to access the dlls so I do not have to place the dll in system32 but contain it in an application folder and access it from there.
What am I missing?
EDIT:
I did find this post interesting and similar but again, it also uses the system32 method which is not the way to go.
If this is a win32 native library, you can "preload" it from a known location using pinvoked LoadLibrary passing a full path of your library as a parameter, somewhere early in your processing pipeline.
When any method from the library decorated with DllImport is called, the runtime will try to load the library (and would fall because the dll cannot be found) but since you preloaded it eariler, loading will succeed (loader checks the library file name, doesn't pay any attention to the directory the library is loaded from).

C++ calling managed COM object can't find dependent assemblies

I've created and registered a managed COM library in C# on my development machine. I've successfully registered it and created a .tlb file with regasm, and successfully imported the tlb into a c++ console app used for testing.
My COM assembly is called "efcAPI.dll" and it references another assembly that has not been set up for COM or registered in anyway called "efcServerDiscovery.dll". This second dll contains some code used by my COM dll and exists in the same folder as efcAPI.dll.
Everything concerning loading the COM assembly works fine. I can create instances of my classes defined in the COM and call methods from them. However when I call certain methods that use the code defined in efcServerDiscovery.dll I get a _com_error which reports that it could not load file or assembly 'efcServerDiscovery'.
I've verified that everywhere on my hard drive where efcAPI.dll exists there's a copy of efcServerDiscovery.dll (which is just the location I built and registered efcAPI.dll from). I've also attempted to place efcAPI.dll and efcServerDiscovery.dll in the same directory as the c++ app with no success.
Any suggestions as to where the c++ app is looking for the assembly or how to discover where it's looking would be great!
Yes, this is a problem with COM components having non-COM dependencies. Windows doesn't consider the location of the COM DLL when it searches for dependent DLLs. The normal search rules are in effect, the folder that contains the EXE first, Windows directories, current working directory, PATH environment. The location of the COM server does not play a role.
Assuming you don't want to deploy to the EXE folder, none of these are good places to store your DLL, although plenty of installers made the desperation move of storing it in c:\windows\system32 or modify the system PATH environment variable.
One thing you could do is P/Invoke SetDllDirectory() in your C# code before running any code in the DLL. Using Assembly.GetExecutingAssembly().Location will do it. That is however not a safe thing to do though, it might alter the search rules for the app that uses your component.
The only real fix is to install the DLL in the Windows side-by-side cache (WinSxS) and to include a manifest in your C# executable. Given the state of the documentation, I can only wish you the best of luck.
In these situations i always start with Dependency Walker verifying that what & where its trying to load is what i think it is.
fuslogvw will tell you where the CLR is looking for assemblies
Or use GAC.
(here are your characters, stackoverflow)

Categories

Resources