32 bit or 64 bit using c# [duplicate] - c#

In a .NET 2.0 C# application I use the following code to detect the operating system platform:
string os_platform = System.Environment.OSVersion.Platform.ToString();
This returns "Win32NT". The problem is that it returns "Win32NT" even when running on Windows Vista 64-bit.
Is there any other method to know the correct platform (32 or 64 bit)?
Note that it should also detect 64 bit when run as a 32 bit application on Windows 64 bit.

.NET 4 has two new properties in the Environment class, Is64BitProcess and Is64BitOperatingSystem. Interestingly, if you use Reflector you can see they are implemented differently in the 32-bit & 64-bit versions of mscorlib. The 32-bit version returns false for Is64BitProcess and calls IsWow64Process via P/Invoke for Is64BitOperatingSystem. The 64-bit version just returns true for both.

UPDATE: As Joel Coehoorn and others suggest, starting at .NET Framework 4.0, you can just check Environment.Is64BitOperatingSystem.
IntPtr.Size won't return the correct value if running in 32-bit .NET Framework 2.0 on 64-bit Windows (it would return 32-bit).
As Microsoft's Raymond Chen describes, you have to first check if running in a 64-bit process (I think in .NET you can do so by checking IntPtr.Size), and if you are running in a 32-bit process, you still have to call the Win API function IsWow64Process. If this returns true, you are running in a 32-bit process on 64-bit Windows.
Microsoft's Raymond Chen:
How to detect programmatically whether you are running on 64-bit Windows
My solution:
static bool is64BitProcess = (IntPtr.Size == 8);
static bool is64BitOperatingSystem = is64BitProcess || InternalCheckIsWow64();
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWow64Process(
[In] IntPtr hProcess,
[Out] out bool wow64Process
);
public static bool InternalCheckIsWow64()
{
if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) ||
Environment.OSVersion.Version.Major >= 6)
{
using (Process p = Process.GetCurrentProcess())
{
bool retVal;
if (!IsWow64Process(p.Handle, out retVal))
{
return false;
}
return retVal;
}
}
else
{
return false;
}
}

If you're using .NET Framework 4.0, it's easy:
Environment.Is64BitOperatingSystem
See Environment.Is64BitOperatingSystem Property (MSDN).

This is just an implementation of what's suggested above by Bruno Lopez, but works on Win2k + all WinXP service packs. Just figured I'd post it so other people didn't have roll it by hand. (would have posted as a comment, but I'm a new user!)
[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
public extern static IntPtr LoadLibrary(string libraryName);
[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
public extern static IntPtr GetProcAddress(IntPtr hwnd, string procedureName);
private delegate bool IsWow64ProcessDelegate([In] IntPtr handle, [Out] out bool isWow64Process);
public static bool IsOS64Bit()
{
if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor()))
{
return true;
}
else
{
return false;
}
}
private static IsWow64ProcessDelegate GetIsWow64ProcessDelegate()
{
IntPtr handle = LoadLibrary("kernel32");
if ( handle != IntPtr.Zero)
{
IntPtr fnPtr = GetProcAddress(handle, "IsWow64Process");
if (fnPtr != IntPtr.Zero)
{
return (IsWow64ProcessDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)fnPtr, typeof(IsWow64ProcessDelegate));
}
}
return null;
}
private static bool Is32BitProcessOn64BitProcessor()
{
IsWow64ProcessDelegate fnDelegate = GetIsWow64ProcessDelegate();
if (fnDelegate == null)
{
return false;
}
bool isWow64;
bool retVal = fnDelegate.Invoke(Process.GetCurrentProcess().Handle, out isWow64);
if (retVal == false)
{
return false;
}
return isWow64;
}

The full answer is this (taken from both stefan-mg, ripper234 and BobbyShaftoe's answer):
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);
private bool Is64Bit()
{
if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor()))
{
return true;
}
else
{
return false;
}
}
private bool Is32BitProcessOn64BitProcessor()
{
bool retVal;
IsWow64Process(Process.GetCurrentProcess().Handle, out retVal);
return retVal;
}
First check if you're in a 64 bit process. If you're not, check if the 32 bit process is a Wow64Process.

Microsoft has put a code sample for this:
http://1code.codeplex.com/SourceControl/changeset/view/39074#842775
It looks like this:
/// <summary>
/// The function determines whether the current operating system is a
/// 64-bit operating system.
/// </summary>
/// <returns>
/// The function returns true if the operating system is 64-bit;
/// otherwise, it returns false.
/// </returns>
public static bool Is64BitOperatingSystem()
{
if (IntPtr.Size == 8) // 64-bit programs run only on Win64
{
return true;
}
else // 32-bit programs run on both 32-bit and 64-bit Windows
{
// Detect whether the current process is a 32-bit process
// running on a 64-bit system.
bool flag;
return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") &&
IsWow64Process(GetCurrentProcess(), out flag)) && flag);
}
}
/// <summary>
/// The function determins whether a method exists in the export
/// table of a certain module.
/// </summary>
/// <param name="moduleName">The name of the module</param>
/// <param name="methodName">The name of the method</param>
/// <returns>
/// The function returns true if the method specified by methodName
/// exists in the export table of the module specified by moduleName.
/// </returns>
static bool DoesWin32MethodExist(string moduleName, string methodName)
{
IntPtr moduleHandle = GetModuleHandle(moduleName);
if (moduleHandle == IntPtr.Zero)
{
return false;
}
return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero);
}
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule,
[MarshalAs(UnmanagedType.LPStr)]string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
There is a WMI version available as well (for testing remote machines).

You can also check for the PROCESSOR_ARCHITECTURE environment variable.
It either doesn't exist or is set to "x86" on 32-bit Windows.
private int GetOSArchitecture()
{
string pa =
Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
return ((String.IsNullOrEmpty(pa) ||
String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? 32 : 64);
}

From Chriz Yuen blog
C# .Net 4.0 Introduced two new environment property
Environment.Is64BitOperatingSystem;
Environment.Is64BitProcess;
Please be careful when you use these both property.
Test on Windows 7 64bits Machine
//Workspace: Target Platform x86
Environment.Is64BitOperatingSystem True
Environment.Is64BitProcess False
//Workspace: Target Platform x64
Environment.Is64BitOperatingSystem True
Environment.Is64BitProcess True
//Workspace: Target Platform Any
Environment.Is64BitOperatingSystem True
Environment.Is64BitProcess True

Quickest way:
if(IntPtr.Size == 8) {
// 64 bit machine
} else if(IntPtr.Size == 4) {
// 32 bit machine
}
Note: this is very direct and works correctly on 64-bit only if the program does not force execution as a 32-bit process (e.g. through <Prefer32Bit>true</Prefer32Bit> in the project settings).

Try this:
Environment.Is64BitOperatingSystem
Environment.Is64BitProcess

#foobar: You are right, it is too easy ;)
In 99% of the cases, developers with weak system administrator backgrounds ultimately fail to realize the power Microsoft has always provided for anyone to enumerate Windows.
System administrators will always write better and simpler code when it comes to such a point.
Nevertheless, one thing to note, build configuration must be AnyCPU for this environment variable to return the correct values on the correct systems:
System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
This will return "X86" on 32-bit Windows, and "AMD64" on 64-bit Windows.

Using dotPeek helps to see how the framework actually does it. With that in mind, here's what I've come up with:
public static class EnvironmentHelper
{
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll")]
static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32")]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll")]
static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
public static bool Is64BitOperatingSystem()
{
// Check if this process is natively an x64 process. If it is, it will only run on x64 environments, thus, the environment must be x64.
if (IntPtr.Size == 8)
return true;
// Check if this process is an x86 process running on an x64 environment.
IntPtr moduleHandle = GetModuleHandle("kernel32");
if (moduleHandle != IntPtr.Zero)
{
IntPtr processAddress = GetProcAddress(moduleHandle, "IsWow64Process");
if (processAddress != IntPtr.Zero)
{
bool result;
if (IsWow64Process(GetCurrentProcess(), out result) && result)
return true;
}
}
// The environment must be an x86 environment.
return false;
}
}
Example usage:
EnvironmentHelper.Is64BitOperatingSystem();

Use these two environment variables (pseudo code):
if (PROCESSOR_ARCHITECTURE = x86 &&
isDefined(PROCESSOR_ARCHITEW6432) &&
PROCESSOR_ARCHITEW6432 = AMD64) {
//64 bit OS
}
else
if (PROCESSOR_ARCHITECTURE = AMD64) {
//64 bit OS
}
else
if (PROCESSOR_ARCHITECTURE = x86) {
//32 bit OS
}
Refer to the blog post HOWTO: Detect Process Bitness.

I used this check with success on many operating systems:
private bool Is64BitSystem
{
get
{
return Directory.Exists(Environment.ExpandEnvironmentVariables(#"%windir%\SysWOW64"));
}
}
This folder is always named "SysWOW64", no matter of the language of the operating system. This works for .NET Framework 1.1 or above.

I need to do this, but I also need to be able as an admin do it remotely, either case this seems to work quite nicely for me:
public static bool is64bit(String host)
{
using (var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, host))
using (var key = reg.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\"))
{
return key.GetValue("ProgramFilesDir (x86)") !=null;
}
}

This is a solution based on Microsoft's code at http://1code.codeplex.com/SourceControl/changeset/view/39074#842775. It uses extension methods for easy code reuse.
Some possible usage is shown below:
bool bIs64BitOS = System.Environment.OSVersion.IsWin64BitOS();
bool bIs64BitProc = System.Diagnostics.Process.GetCurrentProcess().Is64BitProc();
//Hosts the extension methods
public static class OSHelperTools
{
/// <summary>
/// The function determines whether the current operating system is a
/// 64-bit operating system.
/// </summary>
/// <returns>
/// The function returns true if the operating system is 64-bit;
/// otherwise, it returns false.
/// </returns>
public static bool IsWin64BitOS(this OperatingSystem os)
{
if (IntPtr.Size == 8)
// 64-bit programs run only on Win64
return true;
else// 32-bit programs run on both 32-bit and 64-bit Windows
{ // Detect whether the current process is a 32-bit process
// running on a 64-bit system.
return Process.GetCurrentProcess().Is64BitProc();
}
}
/// <summary>
/// Checks if the process is 64 bit
/// </summary>
/// <param name="os"></param>
/// <returns>
/// The function returns true if the process is 64-bit;
/// otherwise, it returns false.
/// </returns>
public static bool Is64BitProc(this System.Diagnostics.Process p)
{
// 32-bit programs run on both 32-bit and 64-bit Windows
// Detect whether the current process is a 32-bit process
// running on a 64-bit system.
bool result;
return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") && IsWow64Process(p.Handle, out result)) && result);
}
/// <summary>
/// The function determins whether a method exists in the export
/// table of a certain module.
/// </summary>
/// <param name="moduleName">The name of the module</param>
/// <param name="methodName">The name of the method</param>
/// <returns>
/// The function returns true if the method specified by methodName
/// exists in the export table of the module specified by moduleName.
/// </returns>
static bool DoesWin32MethodExist(string moduleName, string methodName)
{
IntPtr moduleHandle = GetModuleHandle(moduleName);
if (moduleHandle == IntPtr.Zero)
return false;
return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero);
}
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)]string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
}

Here is the direct approach in C# using DllImport from this page.
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);
public static bool Is64Bit()
{
bool retVal;
IsWow64Process(Process.GetCurrentProcess().Handle, out retVal);
return retVal;
}

I'm using the followin code. Note: It's made for an AnyCPU project.
public static bool Is32bitProcess(Process proc) {
if (!IsThis64bitProcess()) return true; // We're in 32-bit mode, so all are 32-bit.
foreach (ProcessModule module in proc.Modules) {
try {
string fname = Path.GetFileName(module.FileName).ToLowerInvariant();
if (fname.Contains("wow64")) {
return true;
}
} catch {
// What on earth is going on here?
}
}
return false;
}
public static bool Is64bitProcess(Process proc) {
return !Is32bitProcess(proc);
}
public static bool IsThis64bitProcess() {
return (IntPtr.Size == 8);
}

I found this to be the best way to check for the platform of the system and the process:
bool 64BitSystem = Environment.Is64BitOperatingSystem;
bool 64BitProcess = Environment.Is64BitProcess;
The first property returns true for 64-bit system, and false for 32-bit.
The second property returns true for 64-bit process, and false for 32-bit.
The need for these two properties is because you can run 32-bit processes on 64-bit system, so you will need to check for both the system and the process.

All fine, but this should also work from env:
PROCESSOR_ARCHITECTURE=x86
..
PROCESSOR_ARCHITECTURE=AMD64
Too easy, maybe ;-)

Here's a Windows Management Instrumentation (WMI) approach:
string _osVersion = "";
string _osServicePack = "";
string _osArchitecture = "";
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_OperatingSystem");
ManagementObjectCollection collection = searcher.Get();
foreach (ManagementObject mbo in collection)
{
_osVersion = mbo.GetPropertyValue("Caption").ToString();
_osServicePack = string.Format("{0}.{1}", mbo.GetPropertyValue("ServicePackMajorVersion").ToString(), mbo.GetPropertyValue("ServicePackMinorVersion").ToString());
try
{
_osArchitecture = mbo.GetPropertyValue("OSArchitecture").ToString();
}
catch
{
// OSArchitecture only supported on Windows 7/Windows Server 2008
}
}
Console.WriteLine("osVersion : " + _osVersion);
Console.WriteLine("osServicePack : " + _osServicePack);
Console.WriteLine("osArchitecture: " + _osArchitecture);
/////////////////////////////////////////
// Test on Windows 7 64-bit
//
// osVersion : Microsoft Windows 7 Professional
// osservicePack : 1.0
// osArchitecture: 64-bit
/////////////////////////////////////////
// Test on Windows Server 2008 64-bit
// --The extra r's come from the registered trademark
//
// osVersion : Microsoftr Windows Serverr 2008 Standard
// osServicePack : 1.0
// osArchitecture: 64-bit
/////////////////////////////////////////
// Test on Windows Server 2003 32-bit
// --OSArchitecture property not supported on W2K3
//
// osVersion : Microsoft(R) Windows(R) Server 2003, Standard Edition
// osServicePack : 2.0
// osArchitecture:

OSInfo.Bits
using System;
namespace CSharp411
{
class Program
{
static void Main( string[] args )
{
Console.WriteLine( "Operation System Information" );
Console.WriteLine( "----------------------------" );
Console.WriteLine( "Name = {0}", OSInfo.Name );
Console.WriteLine( "Edition = {0}", OSInfo.Edition );
Console.WriteLine( "Service Pack = {0}", OSInfo.ServicePack );
Console.WriteLine( "Version = {0}", OSInfo.VersionString );
Console.WriteLine( "Bits = {0}", OSInfo.Bits );
Console.ReadLine();
}
}
}

Include the following code into a class in your project:
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool wow64Process);
public static int GetBit()
{
int MethodResult = "";
try
{
int Architecture = 32;
if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) || Environment.OSVersion.Version.Major >= 6)
{
using (Process p = Process.GetCurrentProcess())
{
bool Is64Bit;
if (IsWow64Process(p.Handle, out Is64Bit))
{
if (Is64Bit)
{
Architecture = 64;
}
}
}
}
MethodResult = Architecture;
}
catch //(Exception ex)
{
//ex.HandleException();
}
return MethodResult;
}
Use it like so:
string Architecture = "This is a " + GetBit() + "bit machine";

Use this to get the installed Windows architecture:
string getOSArchitecture()
{
string architectureStr;
if (Directory.Exists(Environment.GetFolderPath(
Environment.SpecialFolder.ProgramFilesX86))) {
architectureStr ="64-bit";
}
else {
architectureStr = "32-bit";
}
return architectureStr;
}

Given that the accepted answer is very complex. There are simpler ways. Mine is a variation of alexandrudicu's anaswer.
Given that 64-bit windows install 32-bit applications in Program Files (x86) you can check if that folder exists, using environment variables (to make up for different localizations)
e.g.
private bool Is64BitSystem
{
get
{
return Directory.Exists(Environment.ExpandEnvironmentVariables(#"%PROGRAMFILES(X86)%"));
}
}
This for me is faster and simpler. Given that I also wish to access a specific path under that folder based on OS version.

This question is for .NET 2.0 but still comes up in a google search, and nobody here mentionned that since .NET standard 1.1 / .NET core 1.0, there is now a better way to know the CPU architecture:
System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture
This should theoretically be able to differenciate between x64 and Arm64, though I didn't test it myself.
See the documentation.

Sorry for code of VB.NET, but it easy to port to C#.
It works ok on Win7, x64 with .Net Framework 4.8:
Dim r As String = ""
Using searcher As ManagementObjectSearcher = New System.Management.ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem")
Dim Information As ManagementObjectCollection = searcher.Get()
If Information IsNot Nothing Then
For Each obj As ManagementObject In Information
r = obj("Caption").ToString() & _
" - " & _
obj("OSArchitecture").ToString() ' <--- !!! "64-bit" shown here
Next
End If
MessageBox.Show(r)
End Using

Enjoy ;-)
Function Is64Bit() As Boolean
Return My.Computer.FileSystem.SpecialDirectories.ProgramFiles.Contains("Program Files (x86)")
End Function

Just see if the "C:\Program Files (x86)" exists. If not, then you are on a 32 bit OS. If it does, then the OS is 64 bit (Windows Vista or Windows 7). It seems simple enough...

I use:
Dim drivelet As String = Application.StartupPath.ToString
If Directory.Exists(drivelet(0) & ":\Program Files (x86)") Then
MsgBox("64bit")
Else
MsgBox("32bit")
End if
This gets the path where your application is launched in case you have it installed in various places on the computer. Also, you could just do the general C:\ path since 99.9% of computers out there have Windows installed in C:\.

Related

Create an app for both console usage and windows usage [duplicate]

Is there a way to launch a C# application with the following features?
It determines by command-line parameters whether it is a windowed or console app
It doesn't show a console when it is asked to be windowed and doesn't show a GUI window when it is running from the console.
For example, myapp.exe /help would output to stdout on the console you used, but myapp.exe by itself would launch my Winforms or WPF user interface.
The best answers I know of so far involve having two separate exe and use IPC, but that feels really hacky.
What options do I have and trade-offs can I make to get the behavior described in the example above? I'm open to ideas that are Winform-specific or WPF-specific, too.
Make the app a regular windows app, and create a console on the fly if needed.
More details at this link (code below from there)
using System;
using System.Windows.Forms;
namespace WindowsApplication1 {
static class Program {
[STAThread]
static void Main(string[] args) {
if (args.Length > 0) {
// Command line given, display console
if ( !AttachConsole(-1) ) { // Attach to an parent process console
AllocConsole(); // Alloc a new console
}
ConsoleMain(args);
}
else {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
private static void ConsoleMain(string[] args) {
Console.WriteLine("Command line = {0}", Environment.CommandLine);
for (int ix = 0; ix < args.Length; ++ix)
Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
Console.ReadLine();
}
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AttachConsole(int pid);
}
}
I basically do that the way depicted in Eric's answer, additionally I detach the console with FreeConsole and use the SendKeys command to get the command prompt back.
[DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[DllImport("kernel32.dll")]
private static extern bool AttachConsole(int pid);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FreeConsole();
[STAThread]
static void Main(string[] args)
{
if (args.Length > 0 && (args[0].Equals("/?") || args[0].Equals("/help", StringComparison.OrdinalIgnoreCase)))
{
// get console output
if (!AttachConsole(-1))
AllocConsole();
ShowHelp(); // show help output with Console.WriteLine
FreeConsole(); // detach console
// get command prompt back
System.Windows.Forms.SendKeys.SendWait("{ENTER}");
return;
}
// normal winforms code
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
Write two apps (one console, one windows) and then write another smaller app which based on the parameters given opens up one of the other apps (and then would presumably close itself since it would no longer be needed)?
I've done this by creating two separate apps.
Create the WPF app with this name: MyApp.exe. And create the console app with this name: MyApp.com. When you type your app name in the command line like this MyApp or MyApp /help (without .exe extension) the console app with the .com extension will take precedence. You can have your console application invoke the MyApp.exe according to the parameters.
This is exactly how devenv behaves. Typing devenv at the command line will launch Visual Studio's IDE. If you pass parameters like /build, it will remain in the command line.
NOTE: I haven't tested this, but I believe it would work...
You could do this:
Make your app a windows forms application. If you get a request for console, don't show your main form. Instead, use platform invoke to call into the Console Functions in the Windows API and allocate a console on the fly.
(Alternatively, use the API to hide the console in a console app, but you'd probably see the console "flicker" as it was created in this case...)
As far as I am aware there is a flag in the exe that tells it whether to run as console or windowed app. You can flick the flag with tools that come with Visual Studio, but you cann't do this at runtime.
If the exe is compiled as a console, then it will always open a new console if its not started from one.
If the the exe is an application then it can't output to the console. You can spawn a separate console - but it won't behave like a console app.
I the past we have used 2 separate exe's. The console one being a thin wrapper over the forms one (you can reference an exe as you would reference a dll, and you can use the [assembly:InternalsVisibleTo("cs_friend_assemblies_2")] attribute to trust the console one, so you don't have to expose more than you need to).
I would create a solution that is a Windows Form App since there are two functions you can call that will hook into the current console. So you can treat the program like a console program. or by default you can launch the GUI.
The AttachConsole function will not create a new console. For more information about AttachConsole, check out PInvoke: AttachConsole
Below a sample program of how to use it.
using System.Runtime.InteropServices;
namespace Test
{
/// <summary>
/// This function will attach to the console given a specific ProcessID for that Console, or
/// the program will attach to the console it was launched if -1 is passed in.
/// </summary>
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FreeConsole();
[STAThread]
public static void Main()
{
Application.ApplicationExit +=new EventHandler(Application_ApplicationExit);
string[] commandLineArgs = System.Environment.GetCommandLineArgs();
if(commandLineArgs[0] == "-cmd")
{
//attaches the program to the running console to map the output
AttachConsole(-1);
}
else
{
//Open new form and do UI stuff
Form f = new Form();
f.ShowDialog();
}
}
/// <summary>
/// Handles the cleaning up of resources after the application has been closed
/// </summary>
/// <param name="sender"></param>
public static void Application_ApplicationExit(object sender, System.EventArgs e)
{
FreeConsole();
}
}
One way to do this is to write a Window app that doesn't show a window if the command line arguments indicate it shouldn't.
You can always get the command line arguments and check them before showing the first window.
The important thing to remember to do after AttachConsole() or AllocConsole() calls to get it to work in all cases is:
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
System.IO.StreamWriter sw =
new System.IO.StreamWriter(System.Console.OpenStandardOutput());
sw.AutoFlush = true;
System.Console.SetOut(sw);
System.Console.SetError(sw);
}
I have found that works with or without VS hosting process. With output being sent with System.Console.WriteLine or System.Console.out.WriteLine before call To AttachConsole or AllocConsole. I have included my method below:
public static bool DoConsoleSetep(bool ClearLineIfParentConsole)
{
if (GetConsoleWindow() != System.IntPtr.Zero)
{
return true;
}
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(System.Console.OpenStandardOutput());
sw.AutoFlush = true;
System.Console.SetOut(sw);
System.Console.SetError(sw);
ConsoleSetupWasParentConsole = true;
if (ClearLineIfParentConsole)
{
// Clear command prompt since windows thinks we are a windowing app
System.Console.CursorLeft = 0;
char[] bl = System.Linq.Enumerable.ToArray<char>(System.Linq.Enumerable.Repeat<char>(' ', System.Console.WindowWidth - 1));
System.Console.Write(bl);
System.Console.CursorLeft = 0;
}
return true;
}
int Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
if (Error == ERROR_ACCESS_DENIED)
{
if (log.IsDebugEnabled) log.Debug("AttachConsole(ATTACH_PARENT_PROCESS) returned ERROR_ACCESS_DENIED");
return true;
}
if (Error == ERROR_INVALID_HANDLE)
{
if (AllocConsole())
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(System.Console.OpenStandardOutput());
sw.AutoFlush = true;
System.Console.SetOut(sw);
System.Console.SetError(sw);
return true;
}
}
return false;
}
I also called this when I was done in case I needed command prompt to redisplay when I was done doing output.
public static void SendConsoleInputCR(bool UseConsoleSetupWasParentConsole)
{
if (UseConsoleSetupWasParentConsole && !ConsoleSetupWasParentConsole)
{
return;
}
long LongNegOne = -1;
System.IntPtr NegOne = new System.IntPtr(LongNegOne);
System.IntPtr StdIn = GetStdHandle(STD_INPUT_HANDLE);
if (StdIn == NegOne)
{
return;
}
INPUT_RECORD[] ira = new INPUT_RECORD[2];
ira[0].EventType = KEY_EVENT;
ira[0].KeyEvent.bKeyDown = true;
ira[0].KeyEvent.wRepeatCount = 1;
ira[0].KeyEvent.wVirtualKeyCode = 0;
ira[0].KeyEvent.wVirtualScanCode = 0;
ira[0].KeyEvent.UnicodeChar = '\r';
ira[0].KeyEvent.dwControlKeyState = 0;
ira[1].EventType = KEY_EVENT;
ira[1].KeyEvent.bKeyDown = false;
ira[1].KeyEvent.wRepeatCount = 1;
ira[1].KeyEvent.wVirtualKeyCode = 0;
ira[1].KeyEvent.wVirtualScanCode = 0;
ira[1].KeyEvent.UnicodeChar = '\r';
ira[1].KeyEvent.dwControlKeyState = 0;
uint recs = 2;
uint zero = 0;
WriteConsoleInput(StdIn, ira, recs, out zero);
}
Hope this helps...
No 1 is easy.
No 2 can't be done, I don't think.
The docs say:
Calls to methods such as Write and WriteLine have no effect in Windows applications.
The System.Console class is initialized differently in console and GUI applications. You can verify this by looking at the Console class in the debugger in each application type. Not sure if there's any way to re-initialize it.
Demo:
Create a new Windows Forms app, then replace the Main method with this:
static void Main(string[] args)
{
if (args.Length == 0)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
Console.WriteLine("Console!\r\n");
}
}
The idea is that any command line parameters will print to the console and exit. When you run it with no arguments, you get the window. But when you run it with a command line argument, nothing happens.
Then select the project properties, change the project type to "Console Application", and recompile. Now when you run it with an argument, you get "Console!" like you want. And when you run it (from the command line) with no arguments, you get the window. But the command prompt won't return until you exit the program. And if you run the program from Explorer, a command window will open and then you get a window.
I have worked out a way to do this including using stdin, but I must warn you that it is not pretty.
The problem with using stdin from an attached console is that the shell will also read from it. This causes the input to sometimes go to your app but sometimes to the shell.
The solution is to block the shell for the duration of the apps lifetime (although technically you could try to block it only when you need input). The way I choose to do this is by sending keystrokes to the shell to run a powershell command that waits for the app to terminate.
Incidentally this also fixes the problem of the prompt not getting back after the app terminates.
I have briefly attempted to get it to work from the powershell console as well. The same principles apply, but I didn't get it to execute my command. It might be that powershell has some security checks to prevent running commands from other applications. Because I don't use powershell much I didn't look into it.
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AllocConsole();
[DllImport("kernel32", SetLastError = true)]
private static extern bool AttachConsole(int dwProcessId);
private const uint STD_INPUT_HANDLE = 0xfffffff6;
private const uint STD_OUTPUT_HANDLE = 0xfffffff5;
private const uint STD_ERROR_HANDLE = 0xfffffff4;
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(uint nStdHandle);
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern int SetStdHandle(uint nStdHandle, IntPtr handle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetConsoleProcessList(int[] ProcessList, int ProcessCount);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
/// <summary>
/// Attach to existing console or create new. Must be called before using System.Console.
/// </summary>
/// <returns>Return true if console exists or is created.</returns>
public static bool InitConsole(bool createConsole = false, bool suspendHost = true) {
// first try to attach to an existing console
if (AttachConsole(-1)) {
if (suspendHost) {
// to suspend the host first try to find the parent
var processes = GetConsoleProcessList();
Process host = null;
string blockingCommand = null;
foreach (var proc in processes) {
var netproc = Process.GetProcessById(proc);
var processName = netproc.ProcessName;
Console.WriteLine(processName);
if (processName.Equals("cmd", StringComparison.OrdinalIgnoreCase)) {
host = netproc;
blockingCommand = $"powershell \"& wait-process -id {Process.GetCurrentProcess().Id}\"";
} else if (processName.Equals("powershell", StringComparison.OrdinalIgnoreCase)) {
host = netproc;
blockingCommand = $"wait-process -id {Process.GetCurrentProcess().Id}";
}
}
if (host != null) {
// if a parent is found send keystrokes to simulate a command
var cmdWindow = host.MainWindowHandle;
if (cmdWindow == IntPtr.Zero) Console.WriteLine("Main Window null");
foreach (char key in blockingCommand) {
SendChar(cmdWindow, key);
System.Threading.Thread.Sleep(1); // required for powershell
}
SendKeyDown(cmdWindow, Keys.Enter);
// i haven't worked out how to get powershell to accept a command, it might be that this is a security feature of powershell
if (host.ProcessName == "powershell") Console.WriteLine("\r\n *** PRESS ENTER ***");
}
}
return true;
} else if (createConsole) {
return AllocConsole();
} else {
return false;
}
}
private static void SendChar(IntPtr cmdWindow, char k) {
const uint WM_CHAR = 0x0102;
IntPtr result = PostMessage(cmdWindow, WM_CHAR, ((IntPtr)k), IntPtr.Zero);
}
private static void SendKeyDown(IntPtr cmdWindow, Keys k) {
const uint WM_KEYDOWN = 0x100;
const uint WM_KEYUP = 0x101;
IntPtr result = SendMessage(cmdWindow, WM_KEYDOWN, ((IntPtr)k), IntPtr.Zero);
System.Threading.Thread.Sleep(1);
IntPtr result2 = SendMessage(cmdWindow, WM_KEYUP, ((IntPtr)k), IntPtr.Zero);
}
public static int[] GetConsoleProcessList() {
int processCount = 16;
int[] processList = new int[processCount];
// supposedly calling it with null/zero should return the count but it didn't work for me at the time
// limiting it to a fixed number if fine for now
processCount = GetConsoleProcessList(processList, processCount);
if (processCount <= 0 || processCount >= processList.Length) return null; // some sanity checks
return processList.Take(processCount).ToArray();
}

Replacement for CultureInfo.GetCultures in .NET Windows Store apps

CultureInfo.GetCultures does not exist in the .NET API for Windows Store apps. How could we read all available cultures instead?
I know about the Languages list and the primary application language. I could read all languages that are available for the app that way. But I need to read all cultures (languages) that are available on the system. Previously it was easy using CultureInfo.GetCultures.
James' comment pointed me in the right direction. Here is the code I developed. I checked the code using a unit test to ensure that the returned neutral, specific and all cultures are identical with the cultures CultureInfo.GetCultures returns (and they indeed are :-)).
public class LocalesRetrievalException : Exception
{
public LocalesRetrievalException(string message)
: base(message)
{
}
}
public static class CultureHelper
{
#region Windows API
private delegate bool EnumLocalesProcExDelegate(
[MarshalAs(UnmanagedType.LPWStr)]String lpLocaleString,
LocaleType dwFlags, int lParam);
[DllImport(#"kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool EnumSystemLocalesEx(EnumLocalesProcExDelegate pEnumProcEx,
LocaleType dwFlags, int lParam, IntPtr lpReserved);
private enum LocaleType : uint
{
LocaleAll = 0x00000000, // Enumerate all named based locales
LocaleWindows = 0x00000001, // Shipped locales and/or replacements for them
LocaleSupplemental = 0x00000002, // Supplemental locales only
LocaleAlternateSorts = 0x00000004, // Alternate sort locales
LocaleNeutralData = 0x00000010, // Locales that are "neutral" (language only, region data is default)
LocaleSpecificData = 0x00000020, // Locales that contain language and region data
}
#endregion
public enum CultureTypes : uint
{
SpecificCultures = LocaleType.LocaleSpecificData,
NeutralCultures = LocaleType.LocaleNeutralData,
AllCultures = LocaleType.LocaleWindows
}
public static IReadOnlyCollection<CultureInfo> GetCultures(
CultureTypes cultureTypes)
{
List<CultureInfo> cultures = new List<CultureInfo>();
EnumLocalesProcExDelegate enumCallback = (locale, flags, lParam) =>
{
try
{
cultures.Add(new CultureInfo(locale));
}
catch (CultureNotFoundException)
{
// This culture is not supported by .NET (not happened so far)
// Must be ignored.
}
return true;
};
if (EnumSystemLocalesEx(enumCallback, (LocaleType)cultureTypes, 0,
(IntPtr)0) == false)
{
int errorCode = Marshal.GetLastWin32Error();
throw new LocalesRetrievalException("Win32 error " + errorCode +
" while trying to get the Windows locales");
}
// Add the two neutral cultures that Windows misses
// (CultureInfo.GetCultures adds them also):
if (cultureTypes == CultureTypes.NeutralCultures ||
cultureTypes == CultureTypes.AllCultures)
{
cultures.Add(new CultureInfo("zh-CHS"));
cultures.Add(new CultureInfo("zh-CHT"));
}
return new ReadOnlyCollection<CultureInfo>(cultures);
}
}

C# works on 32bit but not 64bit

The code below works perfectly on my 32bit machine but I have tested the code now on my 64bit machine, I expected it to work as I was calling the 64bit version of the cscript.exe.
Instead the code gets to the point where it runs the script and then waits for exactly 30seconds then exits the script and continues the rest of the program. The script however appears not to run, (it works fine if I run it manually).
using (var ServerProcess = new System.Diagnostics.Process())
{
var fileInformation = new FileInfo(VBScriptToRun);
string processFileName = IntPtr.Size == 8 ? #"c:\windows\sysWOW64\cscript.exe " : #"c:\windows\system32\cscript.exe ";
string processWorkDir = IntPtr.Size == 8 ? #"c:\windows\sysWOW64\" : #"c:\windows\system32\";
string processArguments = fileInformation.FullName;
ServerProcess.StartInfo.FileName = processFileName;
ServerProcess.StartInfo.WorkingDirectory = processWorkDir;
ServerProcess.StartInfo.Arguments = processArguments;
ServerProcess.StartInfo.CreateNoWindow = false;
ServerProcess.StartInfo.UseShellExecute = false;
ServerProcess.StartInfo.RedirectStandardOutput = true;
ServerProcess.StartInfo.LoadUserProfile = true;
EventLogger.Instance.WriteInformation("Total Integration Service Processing File: Starting to launch the specified program");
try
{
ServerProcess.Start();
ServerProcess.WaitForExit();
}catch(Exception e)
{
EventLogger.Instance.WriteInforamtion("Error running script: " + e)
}
// Sample for the Environment.GetFolderPath method
using System;
class Sample
{
public static void Main()
{
Console.WriteLine();
Console.WriteLine("GetFolderPath: {0}",
Environment.GetFolderPath(Environment.SpecialFolder.System));
}
}
/*
This example produces the following results:
GetFolderPath: C:\WINNT\System32
*/
You should not be trying to access the sysWOW64 folder that is the location of 32-bit windows assemblies. Since you indicated that cscript.exe is a 64-bit process the location of cscript.exe on Windows 7 x64 installation would be the System directory
Source: http://msdn.microsoft.com/en-us/library/system.environment.specialfolder
You should also use the following to determine if the operating system is 64-bit or not.
public static bool Is64BitOperatingSystem { get; }
http://msdn.microsoft.com/en-us/library/system.environment.is64bitoperatingsystem.aspx
I should point out that your current method failing because its trying to [based on the lack information this is only a guess] start the 32-bit process. IntPtr.Size is dependant on the process rather than machine.
If you want to use your method your limited to using the following code to do so.
[DllImport("kernel32.dll", SetLastError=true)]
[return:MarshalAs(UnmanagedType.Bool)]
extern static bool IsWow64Process(IntPtr hProcess, [MarshalAs(UnmanagedType.Bool)] out bool isWow64);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError=true)]
extern static IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
extern static IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError=true)]
extern static IntPtr GetProcAddress(IntPtr hModule, string methodName);
You could use
System.Environment.GetEnvironmentVariable( "PROCESSOR_ARCHITECTURE" )
Except that it will return x86 if the process is a 32-bit process.
You are better of using the .NET 4.0 methods.
You could also just use this:
public static bool Is64BitProcess { get; }
This way you know which cscript.exe to actually launch. If your process is 64-bit you should only communicate with a 64-bit process. If its 32-bit then launch only the 32-bit process.
I do believe Windows 7 x64 keeps multiple versions for this exact perhaps in the System and sysWOW64 system directories.
If the process is not actually a 64-bit process then it won't be located at c:\windows\system32 on a 64-bit installation. Looking into it [ why am I forced to research this instead of you? ] Environment.SpecialFolder.SystemX86 will point to the correct location.

Can't figure out how to check if Biometric is present

At work we make our own tablets. Some of the tablets have fingerprint biometrics, some don't. Sometimes a tech forgets to plug it in. I have yet to find a way to check if that device (or any for that matter) is present.
My first approach was to use the GUID for a biometric which is {53D29EF7-377C-4D14-864B-EB3A85769359}. I would search in the registry at hklm\system\currontcontrolset\control\class and check to see if that key is present.
That doesn't work because it seems that Windows 7 has that key present even if you've never had a biometric installed. It worked in XP, but I just tried again on a unit that used to have a biometric but I took it out and that key is still present.
The hardest part about this problem is that I have to work with Windows 7, 7 embedded, xp, and xp embedded.
Next idea was to use WMI, but I couldn't find the correct class to call to check if it is present.
I then found a biometric.dll but that only works in Windows 7.
Sometimes finding a common solution to a problem is not always easy. I'm doing this project in C# but iI'm willing to convert it to any language.
Any ideas on were I should start looking?
With the help of Joshua Drake who gave me an awesome link on how to solve my problem, those are my results:
The code that I am fixing to post is kind of specialized in that it looks for a specific GUID and only looks for the first one. I adapted it from the article about how to disable a device, although this code does not disable anything it merely checks for presence.
public static bool IsDevicePresent(string guid)
{
var info = IntPtr.Zero;
var NullGuid = new Guid(guid);
try
{
info = SetupDiGetClassDevsW(ref NullGuid,null,IntPtr.Zero,DIGCF_PRESENT);
CheckError("SetupDiGetClassDevs");
var devdata = new SP_DEVINFO_DATA();
devdata.cbSize = (UInt32)Marshal.SizeOf(devdata);
// Get first device matching device criterion.
SetupDiEnumDeviceInfo(info,0,out devdata);
// if no items match filter, throw
if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS)
CheckError("No device found matching filter.", 0xcffff);
CheckError("SetupDiEnumDeviceInfo");
}
catch
{
return false;
}
finally
{
if (info != IntPtr.Zero)
SetupDiDestroyDeviceInfoList(info);
}
return true;
}
private static void CheckError(string message, int lasterror = -1)
{
int code = lasterror == -1 ? Marshal.GetLastWin32Error() : lasterror;
if (code != 0)
throw new ApplicationException(String.Format("Error disabling hardware device (Code {0}): {1}",code, message));
}
[DllImport("setupapi.dll", SetLastError = true)]
private static extern IntPtr SetupDiGetClassDevsW([In] ref Guid ClassGuid,[MarshalAs(UnmanagedType.LPWStr)]string Enumerator,IntPtr parent,UInt32 flags);
[DllImport("setupapi.dll", SetLastError = true)]
private static extern bool SetupDiDestroyDeviceInfoList(IntPtr handle);
[DllImport("setupapi.dll", SetLastError = true)]
private static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet,UInt32 memberIndex,[Out] out SP_DEVINFO_DATA deviceInfoData);
//used to find device info from device manager
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVINFO_DATA
{
public UInt32 cbSize;
public Guid classGuid;
public UInt32 devInst;
public IntPtr reserved;
}
private const uint DIGCF_PRESENT = 2;
private const uint ERROR_INVALID_DATA = 13;
private const uint ERROR_NO_MORE_ITEMS = 259;
private const uint ERROR_ELEMENT_NOT_FOUND = 1168;
And here is a simple unit test to prove it works for first device
[Test]
public void TestDevicePresent()
{
var bluetoothClassGuid = "e0cbf06c-cd8b-4647-bb8a-263b43f0f974";
var biometricClassGuid = "53D29EF7-377C-4D14-864B-EB3A85769359";
var cdromdrivClassGiud = "4d36e965-e325-11ce-bfc1-08002be10318";
Assert.False(Native.IsDevicePresent(bluetoothClassGuid));
Assert.False(Native.IsDevicePresent(biometricClassGuid));
Assert.True(Native.IsDevicePresent(cdromdrivClassGiud));
}

How to know my processor is 32 or 64 bits in C#?

How to know my processor is 32 or 64 bits in C#?
For anyone using .NET 4.0 or newer, there is a built-in property System.Environment.Is64BitOperatingSystem to give you this information.
You can query the WMI class Win32_Processor using System.Management.ManagementObject:
ManagementObject mo;
mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'");
ushort i = (ushort)mo["Architecture"];
switch (i)
{
case 0:
return "32 Bit";
break;
case 9:
return "64 Bit";
break;
}
Take a look at the MSDN Library description for other processor codes.
A problem with this is that the user, who is running the program, needs privileges for viewing the WMI.
The easiest way to natively check in C# is:
var size = IntPtr.Size;
size will equal either 4 or 8 but the bigger question is why do you need to know?
You can get the CPU (and more) information from the registry:
HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor
Has 1 or more subkeys (one for each core) called 0, 1, 2 etc. Each subkey contains information on the core including the Identifier which contains either x86 or some 64 bit in text, including processor family and model.
Query the Win32_Processor class via WMI
If you only want to find out if the current application is running as a 32-bit application or a 64-bit application, just use the IntPtr.Size property.
int bits = IntPtr.Size * 8;
To find out information about the actual processor is harder. Here is a library that gets some information, but the page doesn't tell if it gets that specific information. You can get some information from the registry, I haven't checked how much information there is.
You could also use P/Invoke to call GetNativeSystemInfo and get a SystemInfo structure.
Another solution looks like this:
isWow64 = false;
if (System.Environment.OSVersion.Version.Major >= 5 &&
System.Environment.OSVersion.Version.Minor >= 1)
{
var processHandle = GetProcessHandle((uint)
System.Diagnostics.Process.GetCurrentProcess().Id);
bool retVal;
if (!NativeMethods.IsWow64Process(processHandle, out retVal))
{
throw (new Win32Exception());
}
isWow64 = retVal;
}
Alternative solution (but not recommended) :)
public bool Is64bitOS
{
get
{
return Environment.GetEnvironmentVariable("ProgramFiles(x86)")
!= null;
}
}
public string ProgramFilesX86
{
get
{
string programFiles =
Environment.GetEnvironmentVariable("ProgramFiles(x86)");
if (programFiles == null)
{
programFiles = Environment.GetEnvironmentVariable(
"ProgramFiles");
}
return programFiles;
}
}
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);
public static bool Is64Bit()
{
bool retVal;
IsWow64Process(Process.GetCurrentProcess().Handle, out retVal);
return retVal;
}

Categories

Resources