I have several Windows Services that target 32-bit but have been running on a 64-bit OS. I want to benefit from the advantages of 64-bit processes, specifically from a memory standpoint. Outside of changing the platform target from 32 bit to 64 bit, is there anything else I need to do or watch out for?
The answer is - depends. You said:
I have several Windows Services that target 32-bit but have been running on a 64-bit OS
If you build your app targeting x86 - you still run 32-bit even on 64-bit machine.
If you will build your service for AnyCPU, your exe will behave as following:
on 32 bit systems it will attempt to load as x86 and all components must be either x86 or AnyCpu
on 64 bit systems it will attempt to load x86-built assembly as x86 and all components MUST be only x86. And if you have some COM or 3rd party - you may have to compile for x86
on 64 bit systems it will load AnyCPU into x64 context and you better have NO dependencies built for x86. Also, you can build for x64, optimized code.
So, to answer your concrete original sentence - you will need (at minimum) to target AnyCPU or x64 in order to run your app in x64 context. If it is built targeting x86 - you are still running in 32 bit context
Just ensure that all references you use in your Windows Services are also compiled under 'Any' target, otherwhise you will face a problem when trying to load 32bit assemblies in a 64bit Service.
Related
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.
While I was try to use an embedded database which has both 32-and 64-bit versions like SQLite and SQL Server CE in "C# - ANY CPU"
[ Both provide XCOPY deployment for their 32 and 64 bit versions.
Check the following links: -sql server ce private installation- -XCOPY deployment with sqlite- ]
I noticed that when we check "Prefer 32 bit", XCOPY deployment not work,In that case procoess is not 64 bit but try to load ddl from x64 folder and crashes.
If we uncheck "Prefer 32 bit" it works as 64 bit and find also right dlls.
Even if I make my project x86 then it also works and find right ddls under x86.
Why does "prefer 32 bit" compile option have this behaviour? Is it a bug?
I can confirm Hippias Minor's problem - caused me some headache too. SQLite consists of a managed library that chooses which native DLL to load at run-time (either SQLite.Interop.DLL from x64 or x86 directory). This way it does not need to embed the native library (and is thus more portable - same "xcopy deployment" can work on different architectures). This is also the way SQLite is usually installed from NuGet.
The difference between "x86" and "Any CPU w/ prefer 32-bit" (beside being able to run on ARM) is that the first will set the environment variable PROCESSOR_ARCHITECTURE to "x86" while the second will set it to "AMD64"! The issue is described here: PROCESSOR_ARCHITECTURE returns AMD64 in some 32-bit processes
Therefore SQLite (which is using that as a heuristic) will try to load the 64-bit interop DLL and miserarbly fail since it is infact being run as a 32-bit process.
A workaround might be to check Environment.Is64BitProcess and when that is false manually change the environment variable to "x86".
The primary purpose of the 'Prefer 32 bit' is better processor support with the 'CPU Any' setting.
From What AnyCPU Really Means As Of .NET 4.5 and Visual Studio 11
The difference, then, between “Any CPU 32-bit preferred” and “x86” is only this: a .NET application compiled to x86 will fail to run on an ARM Windows system, but an “Any CPU 32-bit preferred” application will run successfully.
On a x64 processor setting this option is essentially the same as using the x86 compile option.
if (!Environment.Is64BitProcess
&& Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
.Equals("AMD64", StringComparison.InvariantCultureIgnoreCase))
{
// Workaround the "Any CPU" w/ "Prefer 32-bit" option from .NET 4.5+
Environment.SetEnvironmentVariable("PROCESSOR_ARCHITECTURE", "x86");
}
before any SQLite code seems to make the thing work.
I have to deploy a C# application on a 64 bit machine though there is a slight probability that it could also be deployed on a 32 bit machine. Should I build two separate executables targeting x86 and x64 platform or should I go for a single executable built targeting 'AnyCPU' platform (specified in the project property's Build option'. Would there be any performace difference between a C# assembly built targeting 'AnyCPU' is deployed on a 64 bit machine vs the same assembly built targeting specifically 'x64' platform ?
No, there is no difference in performance between AnyCPU application running on a 64-bit Windows and an x64 application running on it. The only thing that flag changes are some flags in the header of the compiled assembly and the CLR uses it only to decide whether to use x86 or x64, nothing else
If you were asking whether there is a difference between x86 application running on a 64-bit Windows and an x64 (or AnyCPU), then the answer would be yes. The differences between the two are:
64-bit obviously uses references that are twice as big as 32-bit, which means larger memory consumption, but it also means you can use more memory
64-bit can use more registers that are available only in the 64-bit mode of CPUs
64-bit JIT is different from 32-bit JIT, it has different set of optimizations: for example 64-bit JIT sometimes uses the tail call optimization even if you don't specifically request it using the tail. instruction (which for example C# never does)
As a side note to the above answer. There can be issues with using P/Invoke or DotNetInterop into x86 DLL's on an x64 OS using AnyCPU. In the case where no 64-bit version of the DLL is available, it may be necessary to compile x86 rather than AnyCPU as the OS will try to load the 64-bit version...and fail.
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.
To complete some testing I need to load the 64 bit version of an assembly even though I am running a 32 bit version of Windows. Is this possible?
I'm not sure why you would want to do this, but I suppose you could. If you don't do anything to tell it otherwise, the CLR will load the version of the assembly that is specific to the CPU you are using. That's usually what you want. But I have had an occasion where I needed to load the neutral IL version of an assembly. I used the Load method to specify the version. I haven't tried it (and others here suggest it won't work for an executable assembly), but I suppose you can do the same to specify you want to load the 64 bit version. (You'll have to specify if you want the AMD64 or IA64 version.)
From CLR Via C# (Jeff Richter):
"If your assembly files contain only type-safe managed code,
you are writing code that should work on both 32-bit and 64-bit versions of Windows. No
source code changes are required for your code to run on either version of Windows.
In fact,
the resulting EXE/DLL file produced by the compiler will run on 32-bit Windows as well as
the x64 and IA64 versions of 64-bit Windows! In other words, the one file will run on any
machine that has a version of the .NET Framework installed on it."
" The C# compiler offers a /platform command-line switch. This switch allows you to specify
whether the resulting assembly can run on x86 machines running 32-bit Windows versions
only, x64 machines running 64-bit Windows only, or Intel Itanium machines running 64-bit
Windows only. If you don't specify a platform, the default is anycpu, which indicates that the
resulting assembly can run on any version of Windows.
32 bit Windows can not run 64 bit executables without a VM/emutalor
32 bit Windows can compile for execution on 64 bit Windows
No, you cannot run assemblies that are compiled for 64-bit on a system running the 32-bit version of Windows.