I am designing a client application that will list several applications that I offer. A user will pick the application, and press run, then the application will be downloaded and will be loaded into the client application's domain using Assembly.Load. Here's the snippet of where it gets loaded:
var vAsm = Assembly.Load(client.GetBase());
var vEP = vAsm.EntryPoint;
var vSC = vAsm.GetType(vEP.DeclaringType.FullName).GetMethod("SetClient");
var vInst = vAsm.CreateInstance(vEP.Name);
vSC.Invoke(vInst, new object[] { client, license });
vEP.Invoke(vInst, null);
Problem: Two of the current applications are 32bit. However one of my applications is 64bit.
Question: If I build the client application in AnyCPU, will it be able to load both the 32bit applications AND the 64bit application? Or is there maybe a setting that launches it in 64bit if the machine supports it? This would be ideal, as I would just detect if they are 32bit/64bit and warn them that the one application is not supported on their machine if that's the case.
I will be testing this myself, but maybe somebody could give me some sort of advice to handle this.
Thanks!
To answer your first question, if you compile the application as AnyCPU you let Windows decide which CLR to pick. In my experience, it usually works out to Windows picking the x64 CLR on x64 operating systems and the x86 CLR on x86 operating systems but I'm not certain if that's always a guarantee. AnyCPU does not mean that it gets to run in both. You will only be able to load the version of the application which corresponds to the architecture of the CLR which loaded your client application.
I've had to deal with this sort of thing in some of the applications that I work with at the place where I'm working. I've run into some frustrating bugs when I tried interoperating with applications compiled for a specific architecture and applications compiled for AnyCPU. To make things easier and more predictable, I just ended up compiling the "AnyCPU" applications which had to interact with the "non AnyCPU" applications for each architecture for which they had to interact. There may be some people who have a more sophisticated setup but it wasn't worth the headache for me.
So, the answer to the second question is more advice. I'd just compile the client application for a specific architecture so that you know for sure which architecture that you're dealing with and then add appropriate code to detect the architecture. In fact, I think that you could use some compiler directives to store some sort of indicator as to which architecture that you're running under or even put a "detection" branch specific to each architecture in the compiler directive and that would help you do the warning that you're thinking of doing.
The alternative is to keep the client application as AnyCPU and detect which architecture the application is currently running under (if memory serves, it's IntPtr.Size == 8 for x64 applications but there may be more reliable methods; not sure...) and then only launch the appropriate applications. But still, you have to be mindful of the fact that, even with AnyCPU, you can only load applications of the specific architecture of the CLR which is running your AnyCPU client application.
Does that make sense?
You should build all your binaries in AnyCPU. That way, on a 64-bit OS, they'll run as 64-bit and on a 32-bit OS, they'll run as 32-bit. If you compile to x64, it won't run on a 32-bit OS at all. If you compile to x86, you'll always run as 32-bit, even on a 64-bit OS. The final rule is that you can't mix & match x86 and x64 bins in the same process. The mismatching ones will fail to load.
Related
I made a Universal Windows Platform application. I want to publish this app. My operating system Is x86 and I want to publish to x64. Is this possible?
Generally, this is not possible, 32-bit OS is not compatible with 64-bit assemblies. There used be some ways to do this before by modifying some configuration. But I don't recommend this.
My suggestion is that you might need to create a VM with 64-bit OS on your device and then do the work in the VM. Of course, it's better to get a real device with 64-bit OS. After all, it's always the best practice to test your app completely before you publish.
I have a .NET exe compiled for "AnyCPU", so it can theoretically run in both 32-bit and 64-bit mode (on a 64-bit operating system). Since my exe strongly interacts with MS Office, I need to run it with the same bitness as the installed Office version. (Please take this requirement as granted, I will gladly provide details in the comments, if you are interested.)
Now, I have thought up a solution for this, but it seems more complicated than necessary:
Compile two versions: MyExe32.exe and MyExe64.exe, targeting x86 and x64, respectively, instead of AnyCPU.
Create a launcher application Launcher.exe, which determines the bitness of the locally installed Office version (I know how to do that) and then starts MyExe32.exe or MyExe64.exe.
This would work, but I'd rather have a single, simple MyExe.exe with something like the following pseudo-code during start-up:
if (Environment.Is64BitProcess && IsOffice32BitInstalled)
{
// restart myself in a 32-bit process instead of a 64-bit process
??? // <-- this is where I need help
}
Is that possible? If yes, how?
Notes: I know about the CorFlags utility, but I'd rather have a solution that does not require modifying the exe itself at runtime.
Apparently I don't have reputation enough to post comments, so posting this as an answer instead.
If, as you say, you're deploying to an internal network, I'd recommend using a launcher anwyay.
That way users can have a single network shortcut to the launcher, that doesn't move around. The launcher can determine which bitness is required, and which is the latest release, and launch the EXE for that release.
If you allow users to go directly at the EXE, you will either encounter problems with users having the EXE opened, so you can't overwrite it, or have to create new user shortcuts for every release.
Is restarting via runtime parameter an option?
dotnet run -r win-x86
https://stackoverflow.com/a/63252884/18152293
I have an application that we're trying to migrate to 64bit from 32bit. It's .NET, compiled using the x64 flags. However, we have a large number of DLLs written in FORTRAN 90 compiled for 32bit. The functions in the FORTRAN DLLs are fairly simple: you put data in, you pull data out; no state of any sort. We also don't spend a lot of time there, a total of maybe 3%, but the calculation logic it performs is invaluable.
Can I somehow call the 32bit DLLs from 64bit code? MSDN suggests that I can't, period. I've done some simple hacking and verified this. Everything throws an invalid entry point exception. The only possible solution i've found so far is to create COM+ wrappers for all of the 32bit DLL functions and invoke COM from the 64bit process. This seems like quite a headache. We can also run the process in WoW emulation, but then the memory ceiling wouldn't be increased, capping at around 1.6gb.
Is there any other way to call the 32bit DLLs from a 64bit CLR process?
You'll need to have the 32-bit dll loaded into a separate 32-bit process, and have your 64 bit process communicate with it via interprocess communication. I don't think there is any way a 32-bit dll can be loaded into a 64 bit process otherwise.
There is a pretty good article here:
Accessing 32-bit DLLs from 64-bit code
You need to write your executable processes as 32-bit processes (versus Any CPU or x64) so that they'll be loaded with WoW32 for Vista. This will load them in the 32-bit emulation mode and you won't have the entry point problem. You can leave you libraries in AnyCPU mode, but your executables have to be compiled as x86.
John's answer is correct if you don't want to recompile your existing dlls; however that might be an option for you as well.
Our team is currently migrating our x86 FORTRAN code to x64 to increase the memory ceiling.
I need to check if an executable programm compiled for 64 bit version or for 32 bit version on a Windows system.
I think this question is hard to answer, because a .NET executable in Windows contains code in two forms:
The first part is a native stub that brings in the system's available runtime (for older Windows systems, when the OS loader didn't natively recognize CLR assemblies). It can be either 32-bit or 64-bit, like other Windows applications. You can find out its target architecture by analyzing its PE header.
As you can tell, this is rather straightforward to determine. However, I suspect it may also be largely irrelevant for your use case (and for most use cases), because this first part does't contain the "useful" part of your program and is there primarily for legacy reasons.
The second part is the IL (bytecode) that will get JIT-compiled and then executed. This is the useful part, but this is largely platform agnostic when not running. It's the runtime JIT-generated code that becomes 32-bit or 64-bit.
Now, if the assembly is explicitly built using the x86 or x64 configuration, it will be marked as such and you can find out programmatically without running it whether it's going to be 32-bit or 64-bit.
However, if it's marked as AnyCPU (like most assemblies are, these days) you can't know beforehand what to expect from the JIT-compiled code. You can only really find out at runtime (by asking the environment or by comparing the size of IntPtr for example). Or you can make an educated guess - if your current program is running under 32-bit Windows (but determining this from unmanaged code may be unreliable), you definitely don't have to expect that a .NET assembly would generate 64-bit CPU instructions. However, if you're running under 64-bit Windows (again, the most likely scenario), it won't be that easy, especially considering that the semantics of the AnyCPU configuration changed with .NET 4.5 and you'll have to account for those changes as well.
Now, here's the catch that you might already have realized: The first part and the second part may not match. And they often don't, because the most common scenario is building with the AnyCPU configuration (which will typically yield a 32-bit PE executable) and deploying on 64-bit systems, where the IL will be JIT-compiled to 64-bit instructions.
In the end, you'll have to decide specifically which of the two you want to know (and whether it's worth the trouble). You may also want to explore other options, like taking advantage of the fact that AnyCPU assemblies can load as either 32-bit or 64-bit and in many cases you can use them without checking.
I'm developing an application that uses a plugin mechanism to load libraries. Usually the hosting application runs as 64bit application.
So far everything worked as expected. x64 assemblies could be loaded, AnyCPU could be loaded and x86 assemblies failed. That is - until someone came up with the idea and created an x86 Console Application - and it could be loaded as well.
Why is it possible to load an x86 console application assembly (exe) from a 64bit host process, but it fails to load an x86 library (dll)? Just for clarification - I'm not trying to load x86 dll's and not intend to - just curious why it's allowed to load x86 applications.
(If anyone is interested I can attach the sample code that I used)
The response to this was given in Microsoft Connect some time ago... however I can't seem to find the link.
I did, however, find a thread where they reference it with the response here.
Quoting:
Hi. Thank you for reporting the issue. It looks like you stumbled on an implementation detail - we do not use LoadLibrary for executables and it looks like in this case it does a validation that we do not. I cannot say this difference was the intended behavior, however if we were to to add an additional check now we could break someone, and the issue does not seem serious enough to take the risk.