How To Get Native Processor Architecture

As anyone who has been looking at my blog knows, I have been mostly working on VS integration of the test tools used in our team (apart from setting up and managing TFS for the builds and various other initiatives.)

Anyway, so, I started to author a project template for VS. What's a project without a wizard? So, there is a wizard where you input some basic information and it will generate skeleton test classes, test areas, setup the references, the target platform etc.

The crux of the issue is, the wizard is 32bit. However, it needs to setup the project to target 32bit or 64bit. Depending on the target, the references to the core test infrastructure assemblies have to be added. However, the setup for the test infrastructure will add keys in the following pattern:

x64

HKLM\SOFTWARE\Microsoft\Mantis\x64\InstallDir

HKLM\SOFTWARE\Wow6432Node\Mantis\x86\InstallDir

x86

HKLM\SOFTWARE\Microsoft\Mantis\x86\InstallDir

There is the issue. Let us suppose, I am targetting the 64bit platform from my 32bit wizard. The wizard has to know that the installation folder for the x64 binaries reside in the folder pointed to by the value of the key HKLM\SOFTWARE\Microsoft\Mantis\x64\InstallDir. AFAIK, to do this correctly, the wizard has to figure out whether it is executing as a 32bit binary on WoW64 or as a 32bit binary on a 32bit machine.

After a lot of digging around and playing around with an interop layer (and not being successful I might add), I figured out a solution. I have replicated the code below (it is provided AS-IS).

 namespace SystemInfo
{
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;

    /// 
    /// Interop layer to get information about the host system.
    /// 
    public sealed class SystemInfo
    {
        #region Enumerations

        /// 
        /// Maps to the native processor architecture values.
        /// 
        public enum ProcessorArchitecture : int
        {
            /// PROCESSOR_ARCHITECTURE_UNKNOWN
            None = -1,

            /// PROCESSOR_ARCHITECTURE_INTEL
            Intel = 0,

            /// PROCESSOR_ARCHITECTURE_IA64
            IA64 = 6,

            /// PROCESSOR_ARCHITECTURE_AMD64
            AMD64 = 9
        }

        #endregion

        #region Private Data

        /// The native system info instance.
        private SystemInfoNative nativeInfo;

        #endregion

        #region Constructors

        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The native system info.
        private SystemInfo ( SystemInfoNative nativeInfo )
        {
            this.nativeInfo = nativeInfo;
        }

        #endregion

        #region Properties

        /// 
        /// Gets the processor architecture.
        /// 
        /// The processor architecture.
        public ProcessorArchitecture Architecture
        {
            get
            {
                return (ProcessorArchitecture) Enum.Parse ( typeof ( ProcessorArchitecture ),
                                                            Enum.GetName ( typeof ( ProcessorArchitecture ),
                                                                           this.nativeInfo.processorArchitecture ) );
            }
        }

        #endregion

        #region Static Methods

        /// 
        /// Gets the native system info.
        /// 
        /// 
        public static SystemInfo GetNativeSystemInfo ()
        {
            SystemInfoNative native = new SystemInfoNative ();

            GetNativeSystemInfo ( ref native );

            return new SystemInfo ( native );
        }

        #endregion

        #region Native

        [StructLayout ( LayoutKind.Sequential )]
        private struct SystemInfoNative
        {
            internal ushort processorArchitecture;
            private  ushort reserved;
            internal uint   pageSize;
            internal IntPtr minimumApplicationAddress;
            internal IntPtr maximumApplicationAddress;
            internal IntPtr activeProcessorMask;
            internal uint   numberOfProcessors;
            internal uint   processorType;
            internal uint   allocationGranularity;
            internal ushort processorLevel;
            internal ushort processorRevision;
        }

        [DllImport ( "kernel32.dll" )]
        private static extern void GetNativeSystemInfo ( ref SystemInfoNative lpSystemInfo );

        #endregion
    }
}