Differences between 32 and 64-bit .NET (4) applications - c#

What are the differences between 32 and 64-bit .NET (4) applications?
Often 32-bit applications have problems running on 64-bit machines and conversely. I know I can declare an integer as int32 and int64 (certainly int64 on 32-bit systems make problems). Are there other differences between programming an 32 OR 64-bit or a both 32 AND 64-bit compatible application?

Some differences:
32-bit and 64-bit applications can only load DLLs of the same bitness. This can be an issue for managed projects if your platform target is "Any CPU" and you reference or P/Invoke 32-bit native DLLs. The issue arises when your "Any CPU" program runs on a 64-bit machine, since your application runs as a 64-bit process. When it tries to load the 32-bit native DLL dependency, it will throw an exception (BadImageFormatException) and likely crash.
There are also filesystem and registry issues. A WOW64 process that tries to read from C:\Program Files will end up getting redirected to C:\Program Files (x86) unless it first disables Windows filesystem redirection (see Wow64DisableWow64FsRedirection). For versions of Windows before Windows 7, there were also registry reflection issues that were similar to the filesystem redirection issues mentioned above. The MSDN article Registry Reflection explains it well.
Platform-specific types like IntPtr will have different sizes. This could be an issue in code that assumes a fixed size (serialization, marshaling).
There are separate physical directories for the 32- and 64-bit files in the GAC. For my system, they are at C:\Windows\Microsoft.NET\assembly\GAC_32 and C:\Windows\Microsoft.NET\assembly\GAC_64.
The virtual address space size of 32- and 64-bit applications is different. For 32-bit applications, the size is either 2 GB (default) or 3 GB (with 4GT enabled). For 64-bit applications, the size is 8 TB. The 32-bit address space can be a limitation for very large applications.
A little more obscure, but a lot of interprocess Win32 calls won't work between a 32- and 64-bit process. For example, a 32-bit process can fail when trying to call ReadProcessMemory on a 64-bit process. The same goes for WriteProcessMemory, EnumProcessModules, and a lot of similar methods. This can be seen in C# applications if you try to enumerate the modules of a 64-bit application from a 32-bit application using the System.Diagnostics.Process.Modules API.

In general, I think you should not have any problems with managed code.
Potential problems can come from unmanaged code. For example, because variable sizes are different in 32-bit and 64-bit systems, pointers are different, etc. For example, the size of the int variable in C/C++ depends on the system. As for managed code as already mentioned, WoW can handle that.

x64 managed code will use Streaming SIMD Extensions (SSE) for double/float computation instead of x87 Floating Point Unit (FPU) when using x86 managed code.

In addition to other answers, I would like to add one more thing: we can run software of 32-bit system on 64 but conversely is not possible!

Related

C# : how to use x64 and x86 libraries on same project [duplicate]

My application is built as a x64 application. After moving to VS2010 I got some problems which seems to be related to some x64/x86 mismatch in referenced dlls. Now I'm moving to target .NET4, and I get even more similar problems.
My question is: What precautions do I need to take regarding mixing x64 and x86. Can it be done at all? I thought x64 applications should be able to use x86 dlls without problems. No? What about the other way? Can a x86 application reference an x64 dll - as long as it is being run on an x64 platform? What are the pitfalls I need to be aware of?
No, a 64-bit process can only load 64-bit DLLs and a 32-bit process can only load 32-bit DLLs. What you're probably thinking of is that a 64-bit operating system can run 32-bit processes.
The main issue with .NET is that - prior to VS2010 - executable projects defaulted to "AnyCPU" which means it would load in the "native" format of the OS it's running on (so 32-bit for 32-bit versions of Windows and 64-bit for 64-bit versions of Windows). The problem with that is that if you tested your application on 32-bit Windows (say) then it could break if you load 32-bit DLLs and tried to run on 64-bit Windows.
In VS2010, they defaulted all executable projects to be "x86" (that is, 32-bit) by default which (for the most part) mitigates the problem.
You can run x86 apps on a 64 bit OS using WOW32 emulation. Some pitfalls that I have encountered - you can't mix and match 32/64 in the same process. So if you intend to run IIS as 64 all the assemblies need to be 64 otherwise you'll have to run In 32 bit mode. 64 bit helps some apps more than others. Running SQL sever's 64 bit version provides several advantages over the 32 bit version, biggest advantage being that yo can install more than 4 GB of memory on the target server and that SQL will be able to use more than 4 GB of memory. It does not benefit IIS as much because IIS typically can't use more than 3 gb of memory. My advice would be to make sure your SQL server/os/version are 64 if possible. It's not going to make a. Huge dfference if the other servers are 64 but typically it's easier to work with and find 32 bit versions.

Is it good practice to design c# application under windows 64 bit?

I am new to c# . I am developing a C# application under windows 7 64 bit using visual studio 2015 professional. later when the application is ready I expect to install it in 64 bit or in 32 bit machines.
if I design the application under 64 bit I think it will not work under 32 bit, right? my question is: if I design it and then create setup file under 64 bit computer, what should I do later in order for my application to work under 32 bit windows machines?
Please help me. Thank you
if I design the application under 64 bit I think it will not work under 32 bit, right?
No. You can build an "Any CPU" assembly that will work in both. (You can also build a 32-bit assembly that will work in both, but on 64-bit it runs as a 32-bit app, which is rarely what you want).
my question is: if I design it and then create setup file under 64 bit computer, what should I do later in order for my application to work under 32 bit windows machines?
Test it in one. Selecting "Any CPU" is simple, but forgetting to do so is also simple, especially if you add another project for a library (an Any-CPU application with a 64-bit-only library is essentially 64-bit-only). Testing makes this very obvious, very soon.
If it's a managed application, generally it won't matter. The run-time will auto-magicly sort most problems simply by using Any CPU as target.
I've met 2 problems mostly:
developers who hard-code sizeof(int) to 4
managed applications with un-managed dependancies (like openssl libraries) - in this case you will need to have 2 different builds (one for 32 bit and one for 64 bit)
Your QAs should test your application on all target systems (even if by using virtual machines to do so).
Most .NET developers (I can't speak for C++ guys) use 64bit systems simply because we want performance and to use the newest stuff. All new CPUs support 64 bit for quite some time. It's no longer something exotic.
With .net it doesn't matters, just stick to "Any CPU" compilations and you should not have any problem.
Only exception is if you're using external libraries for an specific platform (unmanaged libraries or managed libraries specifically compiled for x64),
In the case of managed libraries you will need to compile twice, one for x86 and other for x64 with the correct libraries, on the unamnaged case you just need to declare the DllImports twice, one for each platform and use at runtime the correct ones.
It's a bit confusing to be honest...
... later when the application is ready I expect to install it in 64
bit or in 32 bit machines.
All 32-bit applications also work on 64-bit, because Intel/AMD made their AMD64 implementation backward compatible. In other words: regardless if you're using unmanaged or managed code, you can always run it on a 64-bit platform.
The other way around that's not the case, so:
if I design the application under 64 bit I think it will not work
under 32 bit, right?
Yes, correct.
Personally I don't bother anymore with x86 because everyone nowadays has a 64-bit capable processor.
It's usually best to compile to 'Any CPU'. The 'x86' and 'x64' targets are only there to enforce a certain platform. In practice everything is always compiler to .NET IL - which is JIT compiled by the runtime to native assembler.
The JIT uses the 'target flag' or the 'prefer 32-bit' (csproj properties) hint to determine which runtime should run the code. If
you have the 'x86' target or
'prefer 32-bit' (default) or
if you don't have a 64-bit system and don't have the 'prefer 32-bit' checked
it will use the x86 JIT compiler (and runtime). Otherwise it will use the x64 JIT compiler (and runtime).
There are some differences and subtleties that you change when you do this (that all have to do with native interop), but when you stick to normal C# code you shouldn't notice them.
Summary: Personally I seem to make it a habit of not being able to fit my application in 2 GB of RAM (I work what they now call 'big data'), so in those cases the best practice is to use the 'Any CPU' target and uncheck the 'prefer 32-bit'. That said, if you don't need the memory, it's probably better to leave it on as a safeguard.
my question is: if I design it and then create
setup file under 64 bit computer, what should I do later in order for
my application to work under 32 bit windows machines?
You might be surprised, but that's actually a totally different question. Setup systems (e.g. MSI) are highly dependent on the operating system. Most MSI's therefore use hacks to make it work on both platforms. Wix has some quite good documentation about this.

Multi Targeting in C#.NET for 32 bit and 64 bit

Supposing I have a windows app developed based on C#. I want to ensure that it works on 32 bit and 64 bit both. But I don't want to change the config settings or application settings time and again. Is there a way to test both variants?
There are a couple of options.
You can target AnyCPU. If you're program is 100% C#/managed code, with no native dependencies, this will cause it to run 64bit on 64bit Operating systems and 32bit on 32bit Operating systems.
Target x86. This will cause it to run 32bit everywhere, which works properly on 64bit Windows (via WOW64). This works properly if you're using native (32bit) libraries, as well.
Make two builds, and two separate deployments. This allows you to use native code and still run 64bit on 64bit operating systems, but is far more work.
Since 32bit applications run well on 64bit operating systems, there is rarely reason to run the program natively in 64bit. This is typically only really beneficial if you're processing large amounts of data and truly need access to larger memory space than you can get in 32bit processes. In .NET, this typically means you'll want to build 64bit if you're going to use more than 1.2-1.6gb of RAM for your program. Otherwise, 32bit will work fine everywhere.
If you target AnyCPU, most .NET programs will run unaltered on 32-bit or 64-bit machines. The code will be jitted to 32-bit or 64-bit code as appropriate for the target operating system.
The exception where you need to use care is when using interop to unmanaged code.
If you do interop to unmanaged code and require to run as 64-bit on a 64-bit platform, you will have to make two builds.
If you do interop to unmanaged code and can accept running as a 32-bit process, target x86. That avoids two builds, and will run your .NET code as a 32-bit process in 32-bit and 64-bit platforms.

Mixing 32-bit and 64-bit P/Invokes

I've run into a problem that I'm pretty sure I know the answer to, but I figured I'd at least ask and see if there was some "magic bullet" that might save me a huge headache.
Here's the high-level view.
I have a managed application. This application interfaces with hardware via third-party libraries from different vendors. I have full control over the consuming managed app and zero control over the hardware API libraries.
Vendor A provides only a 32-bit native SDK. To allow us to use it on 64-bit systems, we marked the application to run in 32-bit mode. All was well.
We are now integrating with Vendor B, which provides 64-bit-specific native API libraries on 64-bit machines. The 32-bit native DLL from Vendor B will not work on a 64-bit system (tried that). If I build a test harness running as 64-bit or AnyCPU, it works fine. If I mark it as 32-bit, it fails on the P/Invoke calls.
It seems that Vendor A and Vendor B hardware are going to be mutually exclusive on 64-bit PCs, but I'm wondering if anyone has suggestions on how to possibly work around that.
The problem is not a .NET or P/Invoke. It is an OS issue. A 64-bit process can only load 64-bit DLLs. A 32-bit process can only load 32-bit DLLs. The magical Windows-on-Windows (or WoW) layer that lets 32-bit apps run on 64-bit Windows exists between the user-mode process (EXE and DLLs) and the kernel. There is no way to run a 32-bit DLL inside a 64-bit process. The WoW layer exists below that. (Basically WoW is a 32-bit wrapper around the 64-bit Win32 API, which marshals data and function calls between the 32-bit world of the process and the 64-bit world of the operating system.)
Your best/only option is to run your 32-bit and 64-bit components in separate processes and use some form of IPC to communicate. This has the added benefit of decoupling your core application from potentially unstable 3rd-party components. If a 3rd-party component crashes or misbehaves, it's simply a matter of re-starting the process containing that component.
You can make a separate 32-bit process to interact with Vendor A, then communicate with it using WCF.
Since you can't load 32 bit and 64 bit images into the same process, you'll have to use a multi-process solution.
Hopefully someone can suggest a better alternative, but perhaps you could wrap one of the libraries (whichever one has the lowest bandwidth connection to your app) in a separate process, and then communicate with it (e.g. via sockets).

Will a .NET Windows Forms application work in a 64-bit OS or does it need to be modified?

Generally speaking, will a .NET Windows Forms application work in a 64-bit OS or does it need to be modified?
If it doesn't rely on a 32 bit external library (e.g. COM component), it'll work perfectly as a 64 bit process and will leverage its benefits (large address space, x64 instruction set, ...). If it relies on 32 bit stuff, most of the time, you can still run it as a 32 bit application by setting the target platform to x86.
Most .NET applications should work unmodified in 64 bits if they target x86 instead of Any CPU which is the VS.NET default.
According to this link: MSDN - Migrating 32-bit Managed Code to 64-bit.
If you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR.
But if you are using any of the following features:
Invoking platform APIs via p/invoke
Invoking COM objects
Making use of unsafe code
Using marshaling as a mechanism for sharing information
Using serialization as a way of persisting state
it indicates that the application might not be completely compatible.
For the most part it should work just fine. You should be careful if you are doing anything with native code, whether it be unsafe managed code, or interop/PInvoke, but if all of your code is managed you shouldn't have any problems.
A pure .NET application will run on a 64-bit operating system with no modifications.
If you use a C++/CLI library, use architecture specific COM components, or do any P/Invoke calls, you may need to update your application for a 64-bit environment.
Most 64-bit OS's are able to handle 32-bit apps without problems. This is why you see a Program Files (x86) folder on your 64-bit OS to handle a lot of your old 32-bit apps.
As long as you don't mix and match library platforms, you'll be fine. Target x86 when you compile and you should be good to go.

Categories