32 vs 64 bit OS detection

E

Ed Kramer

Greetings,

I am a C# software developer and I'm having some issues with running
applications on both 32 bit and 64 bit architecture. After an extensive
amount of net searching I have found several ways of detection at runtime
each with it's own pitfalls and levels of confidence. In our shop we have
mostly 32 bit machines and 32 bit Operating systems, though we have a few 64
bit machines available outside the office (my home Pc for example). I assume
we will eventually get rid of our w32 machines but I don't know when that
will happen and our code needs to run on both architectures. Our assemblies
are all built as 'Any CPU' rather than as x86 or x64 so that we don't have to
compile two different sets of binaries. So I suppose what I need to know is:
How do I determine what platform I am running under at both run and build
time?

At build time...
I am asking about this because the 32 bit SDK doesnt' work on a 64 bit
machine so the tools for signing, strong naming and manifesting are installed
in a different location on w7 x64 than it would be on Windows XP 32 bit. So
if I create a post build event to handle signing, strong naming and
manifesting it would need to be aware of which platform it is running on so
it can look for the correct mt.exe, sn.exe and signtool.exe whether it is
building on my home x64 W7 machine or at my WinXp 32 machine at work. is
there a macro or pre-processor define or something that can I can reference
in my post build event so I know which path to these executables to use?
Knowing what to use in my post build event would also make my build script
functional. I do work from home on a 64 bit windows 7 machine, and when I
attempt to build, all of my assembly prep fails because the CLR SDK 2.0 is at
a different path than on my 32 bit XP machine at work. Since we have around
30 projects, having to go through each post-build event and REM out the
command line pointing to the 32 bit SDK and remove REM from the 64 bit
command line. Which really isn't fun after the first time you do it. Having a
preprocessor directive or something that could switch between the two would
be preferable because then it would just build no matter what machine I put
it on (assuming you installed the SDK to the default location).

At run time...
Since most of our code revolves around windows services and a utility to
configure them you would think not knowing about architecture would be fine.
However, the configuration utility does look in the registry to find the
install path placed there by our Wix installer. On a 64 bit system, this data
ends up under the Wow6432Node whereas on a 32 bit system it ends up under
HKLM\Software\<manufacturer>\<product>. The Wix installer just shoves it in
there and the underlying OS just handles it. Whereas when I fire up the C#
code, there is no special shim or redirect to put me into Wow6432Node if I
specify the 32 bit version of my path. So, I need to know ahead of time which
architecture I'm running under so i can specify the right path. There is of
course some other things as well but this is the one that most readily comes
to mind.

Thus far I've seen the following run time recommendations
1. Check the size of an Intptr. if it's 4 bytes, then you're on a 32 bit.. 8
bytes and you're on 64 bit - But if you're running as a 32 bit process on a
64 bit OS, this is going to return 4 bytes, not 8.

2. Use the Windows API call IsWow64Process - but this only tells you if your
PROCESS is 32 or 64 bit, not your OS. So the same thing as above. My process
may well be 32, but if you're on a 64 bit OS your registry settings aren't
where you expect them to be.

3. Use the environment variable 'PROCESSOR_ARCHITECTURE'. If you are on a 64
bit processor, it will have the characters '64' in it. - I can't say I like
the idea of searching a string for my answers when it might well change
without notice. Also, this doesnt' tell me what the installed OS is as far as
I can tell. You can have a 64 bit processor architecture running a 32 bit OS.
But thus far this is the closest to what I'm looking for.

4. My own idea would be to open the registry and look for the Wow6432Node.
If it's there, then you're running 64 bit, if not you are running 32 bit.

And during unit tests...
I've created a class which wraps all of the different methods of testing for
architecture specs and I'd like to exercise the methods using Nunit unit
testing. Unfortunately without a way for me to definitively KNOW what
architecture I'm running on I cannot be sure that the methods in my classes
are returning the correct value. I could of course make an assumption and
hard code something but that cancels out the idea of being able to run nunit
on any system and have the unit tests still work. The whole point of unit
tests is to remove the human element as much as possible from testing so as
to reduce human error, having to remember to go in and change a setting to
test on 64 or 32 bit would introduce unnecessary human errors into the mix.

Any help on this would be appreciated. Maybe I'm making this a bit more
complicated than it need be or perhaps I'm jus confused, but it appears like
a bit of a catch 22 to me from my perspective. I can't get the code to work
right unless I can detect my architecture but I can't use some reliable way
to detect it so I have to write my own detection routines... but I can't know
they're correct because I can't detect my architecture in a reliable way to
test them.

Thanks,

Ek
 
P

Peter Duniho

Ed said:
[...]
Any help on this would be appreciated. Maybe I'm making this a bit more
complicated than it need be or perhaps I'm jus confused, but it appears like
a bit of a catch 22 to me from my perspective. I can't get the code to work
right unless I can detect my architecture but I can't use some reliable way
to detect it so I have to write my own detection routines... but I can't know
they're correct because I can't detect my architecture in a reliable way to
test them.

I think the first thing you need to do is be clear about what aspects
you need to address. There are at least two different issues that may
exist:

– CPU architecture for the running process (e.g. your C# program)
– CPU architecture for some other process (e.g. your configuration
program, your SDK, etc.)

You may find it helpful to tabulate the exact combinations you need to
handle, so that you can express better what problem you're trying to solve.

I write that because I found your description somewhat hard to follow;
there are a lot of words, all scrunched together in long, run-on
paragraphs, and it's also not clear what "32 bit SDK" you're concerned
about. It's always easier to answer a question if it's stated in a
clear way.

(In fact, often the easiest way to answer a question is to get the
person to ask it more clearly, at which point they discover that they
already know the answer themselves, and just hadn't realized it :) ).

But, generally: if you need to know the OS version, including
architecture, it's complicated, and if you need to know the architecture
for the current process it's not so complicated (you just check
IntPtr.Size).

For specifics on the knowing the OS version, here's a message post that
I think sums it up pretty well:
http://stackoverflow.com/questions/...dows-64-bit-platform-with-net/1840313#1840313

Note that one of the other answerers points out that .NET will in fact
include specific System.Environment properties to report the OS and
process architecture.

Now, as for your specific questions, it seems that all of them really
come down to OS architecture, not the architecture for the currently
running process. Either because they involve things happening before
your program actually runs, or because they involve things external to
your running program.

To the extent that those issues are connected to the registry, it seems
to me that one way forward is to just not use the registry. .NET has
support for .config files, and encourages you to use them. A .config
file would not (or should not) have any of the platform architecture
issues you're running into; it will just be in the place where you put
it, and your 32- and 64-bit processes can access it equally well.

As for the build-time issues, as I mentioned above, it's not really
clear to me what the specific problems you're having are. Clearly
you're having _some_ kind of problem, but why you should have some kind
of SDK that requires your own build process to special-case according to
OS architecture is not clear to me. Inasmuch as there should be any
difference from architecture to architecture (and of course ideally
there wouldn't be), you should have SDK-related environment variables
that point to the appropriate location for the needed tools.

Unfortunately, so much of your question is stated in generalities,
rather than using specific descriptions of exactly what you're using,
how you're using it, and what errors occur when you do, it's really hard
to offer anything more than broad, very general advice. The lack of
specifics makes the question very "slippery".

Pete
 
W

Wilson, Phil

If your main issue is detecting the path to that service, it seems to me you
should use another way to detect it. The one I have in mind is
MsiGetComponentPath (ProductCode guid of setup, Component guid of service
exe, ...) where both of these guids are in the WiX setup. Maybe
MsiLocateComponent () if you don't care about the ProductCode guid.

Alternatively there are the Service APIs, especially QueryServiceConfig ()
because that returns the install path.
 
P

Patrice

At build time...

You have a PROCESSOR_ARCHITECTURE environment variable (you even talked
about it in the second part ?) that could be tested in a command file.
Also I believe VS comes with a command file that sets the apporopriate path
(shown as VS prompt in the start menu).

This is YOUR computer so I trust you won't mess with this value.
At run time...
1. Check the size of an Intptr. if it's 4 bytes, then you're on a 32 bit..
8
bytes and you're on 64 bit - But if you're running as a 32 bit process on
a
64 bit OS, this is going to return 4 bytes, not 8.

And the problem is ? If this a 32 bit process you are in a 32 bit world and
you shouldn't care about the OS.
And during unit tests...

Not sure how it differs from runtime. Also you could perhaps have a define
you could test with #define (but I don"t find whihc defines are available
out of the box).

Finally you could mimic how it is done in .NET 4 that will have those two
properties out of the box (one is for better discoverability).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top