I need to use a COM-DLL from an external company (so I have no source code) that only works with the compile-option CPU-Target x86.
But my program is a "Any CPU" program and I don't want to change this.
So I read and google a lot and found out that I need 2 processes that communicate with IPC and WCF.
The problem: WCF isn't available with the .Net Framework 2.0.
So what is the best and easiest way to do it without change CPU-Target from my main program?
If you have a x86 target dll, be it a .Net assembly or a native dll then you must host this dll in a 32 bit process - in the case of .Net this means selecting the x86 platform, otherwise your dll wil fail to load on a 64 bit machine.
If you absolutely must have a 64 bit process when possible then your only real means of using this dll will be to create an external 32 bit process that "hosts" the dll and communicated with your main 64 bit process via IPC (interprocess communication). WCF is only 1 method of communicating between processes - its not available in .Net 2.0 however you can still use other methods such as .Net remoting.
See Interprocess communication for Windows in C# (.NET 2.0)
However all of this will be a pain to implement and maintain - unless you have a very good reason just compile your application with the x86 platform instead, at least until the external company release a 64 bit version.
If you don't want to change your assembly to "x86" then you need to use some form of IPC, of which WCF is only one. Another option is to used Named Pipes to communicate between the two processes.
In the past I've always written a .NET wrapper for COM and C++ DLLs and placed it within it's own class library.
The wrapper can deal with all interop calls to the dll.
It also allows you to perform data conversion and error reporting that would be meaningful to both parties (your NET application and the COM DLL).
I would think that this should solve your problem.
EDIT
Actually I've thought further on this and the above process won't work. This is because the X86, x64 and Itanium target processors are so fundamentally different.
edited x64 is able to run x86 targetted code and so can Itanium (which used an emulator and now an extension EM64T)
There's more information here
What you may be able to do though is run your x86 dll within a separate process and implement some form of communication between them. I guess that this is why you mentioned WCF. I say this because x86 software should run on x64 system.
This would mean that your solution would have two executables one x86 and one AnyCPU, as an assembly can only be targetted at one CPU type.
Related
I've read many questions and answers indicating that if I want to link my C# project against native libraries, I can't use AnyCPU platform target but must make separate 32- and 64-bit builds, each linked against the native DLL of the appropriate bitness.
This makes me wonder how the .NET Framework assemblies themselves are, or at least appear to be, built for AnyCPU. That is, when adding a reference to my GUI application, why don't I have to pick the 32-bit or 64-bit version of System.Windows.Forms? I thought this might just be some Visual Studio magic that would resolve to the appropriate GAC subdirectory (GAC_32 or GAC_64), but I searched for System.Windows.Forms.dll in the GAC and found it in:
C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll
Note the "GAC_MSIL". So how does this DLL manage to wrap a native 32-bit API yet remain linkable in a 64-bit application? And why can't I use a similar strategy to make a single C# DLL that links against a native 32-bit library yet remains runnable in 64-bit mode?
Option 1: In GAC you may register 2 versions of assembly one 32 and one 64 bit with exactly same names. Oracle DB Driver for .NET uses this strategy.
Option 2: With your assembly that will be AnyCPU deploy two versions of native DLL and choose proper DLL at runtime (SQLite works like that). As it turns out .NET Framework is intelligent enough to load proper version of native DLL via P/Invoke (Using a 32bit or 64bit dll in C# DllImport)
I had the same problem and ended up using Fody Costura
DLL Files will be shipped as embedded ressources and the lib takes care of the bitness.
You could find an example for SQLite here
The problem I have encountered was that your application needs to have access to the Windows Temp folder to create the assemblies from the ressource. If you dont need it, you could disable it using a config setting createtemporaryassemblies
I created a Library with C# over a year ago under windows 7 32-bit and it works correctly, this library use the "User32.dll" and "Gdi32.dll" libraries.
at first I compiled this library for AnyCPU it work on 32bit but it does not work on win 64bit, I Also compiled it for 64bit CPUs but the same happened again.
my library uses the "RawInput devices" from "User32.dll" and "GetDeviceCaps" from "gdi32.dll".
This article in channel9 says:
Third party DLL's, which are 32 bit in nature, cannot be accessed from 64 bit clients. I have yet to see any workarounds for this that actually work. Apparently .NET DLL's will auto-adjust if compiled with "Any CPU" and called from a 32 bit or 64 bit host client.
And also in this question in MSDN:
A 64bit executable cannot call a 32bit dll and viceversa. Unless you actually need your application to be 64bit, the simplest option is to set it to target x86. This will still allow it to run on both 32 and 64bit versions of Windows.
If for some reason this is inapplicable, a possible solution would be to create a separate 32bit process that would load the 32bit dll, and have your 64bit application communicate with the other process, possibly using IPC (in some trivial case, redirecting the standard input and output can also work, or even just inspecting the return value of the process). In any case, this results in some extra work; I would advise you to review accurately your requirements first.
I have a mixed-mode C++/CLI project which is compiled as x86 and x64 frozen dlls.
I have a C# app that needs to use this project which is compiled as "Any CPU".
How can I properly reference the correct dll from the c# app?
If I right click add reference I must select only 1 of the 2 dlls.
My "ANY CPU" C# app will sometimes run as x64 and sometimes as x86 process.
I've heard you can maybe do this via a smart config file.
There are several ways to deal with this. First one is simplest, acknowledge the fact that your app actually does have a dependency on the target architecture. And that AnyCPU isn't the proper setting. It is very rare to need the humongous virtual address memory space you get from x64, especially since you also want and need to make it work on x86. So set the Platform target of the EXE to x86 and you're done.
Second is concluding that this is simply a deployment problem. All you have to do is copy the x64 build of the mixed-mode assembly when your app is installed on a 64-bit operating system, the x86 build on a 32-bit operating system. You'll need to create a Setup project that takes care of this. The simplest way is to create two of them. Also the only way afaik.
Third is the one with bells on where it works either way, the one you no doubt are asking about. This requires changes to code, project and installer. What you need to do is write a post-build event that create two subdirectories with names like "x86" and "x64". And copy the respective version of the DLL into them. This ensures that the CLR cannot find these assemblies.
In your code you must write an event handler for the AppDomain.CurrentDomain.AssemblyResolve event. Subscribe it in your Main() method, well before you try to use any types from the assembly. The event handler must use Assembly.LoadFrom() to load the correct assembly from the subdirectory, based on the value of IntPtr.Size. It is 8 when you run in 64-bit mode.
I should mention yet another approach but that's generally frowned-upon at SO. Install both assemblies into the GAC. Everything is automatic.
Even if your C++ project compiles twice it should have the same managed interface for both x86 and x64 DLL's. Hence as long as your not using strong name signing it shouldn't matter which version of the DLL you reference. What's important is that the correct version is deployed on the target machine.
I have a C# application that makes use of a DLL as I need C++ to access some unmanaged functionalities of the user32 API (I cannot use PInvoke for that). I compile both the application and the DLL for x86 architectures, and everything works fine on Windows 7 32 bits. Now the problem is, on Windows 7 64 bits, the application crashes when I try to use the feature that relies on the DLL (but all the rest works fine).
I suspect that this is a 32/64 bits issue, so I tried re-compiling the DLL for x64 architectures, and now I can choose at runtime which DLL to load between the x86 and the x64. But it still crashes when I try to use the feature that relies on the DLL (which makes sense as I try to load a 64-bit DLL into a 32-bit program). I haven't tried yet to compile both the application and the DLL for x64. I suspect it would work, however it would require me to have two different installers, and I don't want to go there. Any clue?
When interoping with unmanaged code, you need to ensure your .Net app runs on the same subsystem (32-bit or 64-bit). As you've stated the DLL you're loading is for x86, force the .Net to build for only the x86 platform. This setting is found in your project's properties, on the build tab. The default is any CPU, change the setting to x86 to match your unmanaged DLL and you should be fine regardless if you run on a 64-bit or 32-bit OS.
IS there a different in WebService programming in 32bit and 64bit ?
under server 2003 (C# programming )
thank's in advance
There is really no difference between a 32 and 64 bit C# Web Service program than there is for any other type of C# program. The .Net framework was designed to be a mostly platform agnostic framework and it only creeps up in certain areas. Namely
PInvoke: Ideally this is written in a platform agnostic manner but it can be done incorrectly to be tied to a specific platform
COM Interop: Native component may be tied to a particular architecture
(to re-state Jared's reply in slightly different terms)
If you use pure .net code, then just compile for "Any CPU" (the default) and it will work in 32-bit and 64-bit environments.
However, if any part of your application (e.g. a C++/COM dll) is 32-bit, then you have to change the compile type to "x86" to force the entire application to run under WOW64 (as a 32-bit application), or you have to rebuild/get the dll in a 64-bit native form. Essentially you cannot mix 32-bit and 64-bit code in your application.