C# Cannot Connect To WCF Service When Called From COM Interop - c#

I have a C# class library that works fine when called from a C# application. However, it also supports COM Interop so that older C++ clients can also call it. The C# Class library has a WCF service reference in it. The WCF call works fine from a C# call but when called from COM Interop, I get an error stating:
"Could not find default endpoint element that references contract 'xxxx' in the ServiceModel client configuration section....."
The reference is in the app.config or more specifically the .config which gets built when you build the DLL. It seems that when called from a C# application, the DLL knows where to look for this config file (i.e. the same directory as the dll) and hence finds the needed info. However, when called from COM Interop, it seems it must be looking somewhere else for it and not finding it.
Does anyone know how I fix this and make it work in both scenarios?

Using a .config file in a COM server is quite unpractical. The one that System.Configuration looks for is not associated with the DLL but with the EXE. Is name is foo.exe.config where "foo" is the name of the EXE and must be stored in the same directory as the .exe. A COM server can't predict what EXE is going to load it.
But you can make it work by hand by storing the .config file with the right name in the right directory.

In .NET it is always the executable that has a configuration file, not the .dlls it uses. Even if it is the .dll that needs configuration information, it has to be included in the config file of the application.
By default, the CLR will look for a config file called .config in the same directory as the exe. If this happens to be an old C++ program makes no difference, at least according to my experience. You can just copy the config file to the directory of the C++ program, rename it to match the executable and you're good to go.
If you want a solution that just works everywhere, consider expressing the configuration in code, possibly after manually loading the needed configuration information from some source.

Related

Do binding redirects in app.config for class libraries do anything?

The VS solutions I often work with consist of a single executable project (console app, web app) and many class library projects that are all referenced by the executable.
When working with NuGet and installing packages, there's often an app.config file created for each project, usually containing nothing else than a list of binding redirects that consolidate versions of referenced assemblies. Sometimes there's some third-party library-specific content (like Entity Framework config section), but let's leave that aside for now.
When I build the solution and use the binaries of the main executable project, I see all the class library project assemblies in the build output together with the corresponding *.config files (the app.config file gets renamed to AssemblyName.config when built).
When launching the main executable, do the config files of the class library assemblies take any effect? Or is it just the app.config file of the executable that has an effect in this case? What if there are some binding redirects set up on some of the class library projects, and some different binding redirects set up on the main executable project — How are these combined, which take priority?
I've tried to research this online and from what I've read, it looks to me like the app.config files for non-executable assemblies are useless (with regards to binding redirects). Can someone confirm this or elaborate a bit more on the topic?
If it is that way, is it actually undesirable to have these app.config files created by NuGet in class libraries if they contain just the binding redirects? It feels to me that NuGet shouldn't create those binding redirects for class library projects, as it will only increase the confusion about what settings are actually applied.
I found these existing Stack Overflow questions on the topic, but their accepted answers are actually contradictory even when they're marked as duplicates of each other.
Why NuGet adds app.config with assemblyBinding to LIBRARY projects during a NuGet package update?
Is the bindingRedirect .config file needed or all assemblies in an application?
The accepted answer to the first question mentions that app.config files are actually used during compile-time, which means they could have effect. Sources like MSDN and MSBuild source code are cited there as a proof it's used during compile-time. Unfortunately, I'm not proficient enough in MSBuild to understand how it's being used, and if it's really a valid argument.
Can anybody describe an example scenario to prove that an app.config with binding redirects for a class library can do anything?
I have multiple applications with similar setup - Web application referencing multiple library projects each having their own nuget packages etc., Based on my personal experience the assembly bindings in the library projects are not considered during run time.
The bindings specified web or app config in the root application (web/console) is that only matters. All my library projects are setup with "Copy to Output Directory" setting as "Do not copy" for the app.config file - that way my output folder is not cluttered with dll and their config files.
Here is the link which says how the assembly is loaded and where is it being searched and the sequence of it. No where in the article they talk about individual project config files.
Hope that helps.
According to this old msdn article:
An application configuration file is an XML file used to control assembly binding. It can redirect an application from using one version of a side-by-side assembly to another version of the same assembly. This is called per-application configuration. An application configuration file applies only to a specific application manifest and dependent assemblies. Isolated components compiled with an embedded [ISOLATIONAWARE_MANIFEST_RESOURCE_ID] manifest require a separate application configuration file. Manifests managed with CreateActCtx require a separate application configuration file.
So only dll's with the ISOLATIONAWARE_MANIFEST_RESOURCE_ID set actually use an independent application config, otherwise it's deferred to the main process config file.
For more info on what ISOLATIONAWARE is you can read this other MSDN article that goes more in depth.
ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It
should be used if the dll wants private dependencies other than the
process default. For example, if an dll depends on comctl32.dll
version 6.0.0.0. It should have a resource of type RT_MANIFEST, ID
ISOLATIONAWARE_MANIFEST_RESOURCE_ID to depend on comctl32.dll version
6.0.0.0, so that even if the process executable wants comctl32.dll version 5.1, the dll itself will still use the right version of
comctl32.dll.
The answer is maybe. Depending on the type of project the library file is. Some library projects run in contexts where the library's config file is respected (e.g. Azure Web Roles), but that is not the norm.
See my answer here for more details.
Generally there is only one configuration file and thats the configuration file of the executeable (.exe.config, web.config).
Any assembly redirects have to be placed in the configuration file of the executable.
Configuration files of dlls need to be loaded manually using the ConfigurationManager class. See also this question Equivalent to 'app.config' for a library (DLL)
No, only the app.config of the executable will have effect. For example, if you have a console app hosting a WCF service, and in your WCF service you make use of, for example, ConfigurationManager.AppSettings, the AppSettings will come from the console host app.config file. If you spin up another console application (ConsoleClient) to try connecting to the ConsoleHost, then in the parts where the ConsoleClient can be said to be "executing" (for example in its main method), it will use ConsoleClient's app.config, but as soon as it begins using the WCF service, the WCF service will delegate to use ConsoleHost's app.config. (Note that this last point is more relevant to the details behind WCF though.)
Surprisingly, msdn provided this great source:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?referrer=http://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?referrer=http://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?forum=wcf

Using Log4Net Without DLL

My C# WinForms application is designed to be simple to deploy and I don't like the fact that the log4net.dll becomes an additional file to deploy. Is there a way I can embed it into my application so all the user gets to see if the main .exe file and the backend SQL CE database?
Yes. You can do that using ILMerge.
ILMerge is a utility that can be used to merge multiple .NET assemblies into a single assembly. ILMerge takes a set of input assemblies and merges them into one target assembly. The first assembly in the list of input assemblies is the primary assembly. When the primary assembly is an executable, then the target assembly is created as an executable with the same entry point as the primary assembly.
Here's a GUI for ILMerge to make things easier for you
Well, as a side approach (other than ILMerge),
You can log everything in your server where you have deployed your application using log4net. When you want to retrieve your log, use Webrequest to get the data from the server.
Provided everything will need internet connection to log.

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)

How to use an app.config file when calling a C# dll from C++

How do I use an app.config file for the .Net part when calling a .Net dll from C++ and the data in the config-file must be read at the .Net runtime startup.
If I use have a foo.dll.config that I call from ConfigurationManager.OpenExeConfiguration("foo.dll") I can access application settings. What I would like to do though is to change some information in <system.data>, namely remove a DbProviderFactory and replace it with a new one.
It seems like this can only be done if the code is put in the exectubales app.config file.
But as I am calling the .Net code from C++, I cannot have an app.config for my executable.
Is there some way to specify a configuration file that is sure to be run right after machine.config when the .Net runtime starts, even though I'm calling the .Net dll through C++?
You can have myapp.exe.config, and the called .Net assembly will use it, even if myapp.exe is c++ app. I have done this using outlook.exe.config for my outlook addin.

Categories

Resources