Share via


determine 32 or 64bit OS?

Question

Tuesday, March 6, 2012 6:00 PM

Hello,

Need to determine via script if running on a 32 or 64bit version of windows. It needs to work on server 2003, 2008, and 2008R2, so Win32_Operatingsystem's OSArchitecture property will not work for all (not available on server 2003).

I've seen others say to use the following (copy/paste from MSDN doc)
http://msdn.microsoft.com/en-us/library/aa394373%28v=VS.85%29.aspx : 

The Win32_Processor class has these properties.

AddressWidth

Data type: uint16

Access type: Read-only

On a 32-bit operating system, the value is 32 and on a 64-bit operating system it is 64. This property is inherited from CIM_Processor.

so considering that is a property of the processor, I'm wondering if this can be relied on to determine the OS architecture? Can anyone confirm this is the recommended and reliable way to go? Otherwise, I will write a function that uses OSArchitecture for 2008 and 2008R2 and use the Win32_OperatingSystem 'Name' property for server 2003. Between those two things I know I can reliable return the correct information, but if there is one simple place to check, of course I would rather just do that.

anyone?

All replies (29)

Tuesday, March 6, 2012 6:17 PM ✅Answered | 7 votes

Powershell is built on top of the .NET Framework.

In the .NET Framework, the IntPtr structure represents a pointer or handle in the underlying operating system. And it has a Size property. Just check if it's 4 or 9 bites long.

Assuming only 32-bit or 64-bit:

if ([System.IntPtr]::Size -eq 4) { "32-bit" } else { "64-bit" }

Paulo Morgado


Tuesday, March 6, 2012 6:36 PM ✅Answered | 2 votes

This link should help you:

http://techibee.com/powershell/get-operating-system-architecture32-bit-or-64-bit-using-powershell/689

Thanks & Regards
Bhavik Solanki

Please click “Mark as Answer” if this post answers your question and click "Vote as Helpful if this Post helps you.


Tuesday, March 6, 2012 8:06 PM ✅Answered | 1 vote

there are good odds that if the agent is 32bit on a 64bit system that the

32bit powershell will be run

 

 

Justin Rich
http://jrich523.wordpress.com
PowerShell V3 Guide (Technet)
Please remember to mark the replies as answers if they help and unmark them if they provide no help.


Wednesday, March 7, 2012 7:06 AM ✅Answered | 4 votes

I also looked into this when I was using WMI to gather some data from my servers. On Windows kernel 6 and higher servers it is quite easy you can just do:

gwmi win32_operatingsystem | select osarchitecture

Something that works on Windows kernel 5 and up is this:

gwmi win32_processor | select -first 1 | select addresswidth

Wednesday, March 7, 2012 11:45 AM ✅Answered | 5 votes

Under .NET V4 (so PowerShell V3, or earlier if using a .config to force use of .NET 4) there are properties on [Environment] that directly exposes this:

PS> [environment]::Is64BitOperatingSystem
True
PS> [environment]::Is64BitProcess
True

Richard J Cox


Wednesday, March 7, 2012 8:49 PM ✅Answered | 1 vote

On a 64 bit machine, this is defined in system environment variables:

ProgramFiles(x86)=C:\Program Files (x86)


Tuesday, March 6, 2012 6:18 PM | 1 vote

Using the win32_processor class will tell you about the processor, not the O/S.  The processor may be 64-bit, but have a 32-bit O/S installed.

Grant Ward, a.k.a. Bigteddy

What's new in Powershell 3.0 (Technet Wiki)


Tuesday, March 6, 2012 6:39 PM

Paulo,

That is beautiful! No less than a work of art for the particular question :)

One question though: will this *always* be accurate? The only thing I can think of (which I don't even know is even possible at the moment) is if a 64bit OS was configured specifically to run the 32bit version of .net... ? is that even possible? If it is I'm guessing that might be a scenario that would make this method not work.

I hope that's not possible, because I love your suggested approach.

let me know if you know, I'll also do some googling. BTW, you may be thinking even if that were possible, how often would I really come across it? well, if its possible, I will come across it, my environment is a large server hosting environment 5000+ servers, so I really need to cover all my bases.

thanks again and please let me know if 64bit OS can sometimes be configured to run only 32bit version of .net and therefore make this not work.


Tuesday, March 6, 2012 6:41 PM

Bigteddy, yea, that's what I thought also... but since the MSDN doc says "On a 32-bit operating system, the value is 32 and on a 64-bit operating system it is 64." I wasn't sure if this may be a case where the processor class actually yields some operating system specific info... anyone else know about that particular one?


Tuesday, March 6, 2012 6:53 PM

thanks Bhavik, that link (in the comments section) also said the 'addressWidth' of 'Win32_Processor' will do the job, and for the OS, not the CPU.


Tuesday, March 6, 2012 6:57 PM

Paulo,

That is beautiful! No less than a work of art for the particular question :)

This method will only work when run on the system itself.  So you would need Powershell (with remoting) installed on all your target servers for this to work.

I think you will have to make do with WMI, and write code to distinguish between 2003 and others.

Grant Ward, a.k.a. Bigteddy

What's new in Powershell 3.0 (Technet Wiki)


Tuesday, March 6, 2012 7:37 PM

Bigteddy, thanks again for the input.

All the scripts will actually be executed locally (delivered via Tivoli Endpoint Manager to it's agent which will execute it locally).

I know I can get to the right answer via wmi (using a combination of properties), but the main question here is if I still need to do that, or if there is one check that will work on all... and so far, there are two potential options that are one checks that will work on all. Both Paulo's option and the Win32_Processor's AddressWidth property.

As of now, I want to use Paulo's option, but I'm uncertain about the scenario of someone forcing a 64bit OS to only use 32bit version of .net... I don't know if that is even possible. I know you can create a 32bit .net assembly and force it to run in a 32bit process on a 64bit OS, but in my particular case, powershell will be executed and passed a file to run... no explicit path, so it will use the path environment variable and typically that means on 32bit OS's 32bit version of PS will run, and on 64bit OS's, 64bit version of PS will run, each using that particular version of .net. I have confirmed using Paulo's option on 32bit powershell running on 64bit OS will return "32-bit". But I don't think that case will happen, for me, which is running from an agent that just issues the powershell command with parameters for a script file to run etc... the only case I think this could break is if there is *some* way that a 64bit OS can be configured to *only* use the 32bit version of .net.

anyone further input from anyone? all your help is appreciated, everyone. thanks.


Tuesday, March 6, 2012 7:47 PM

So if I understand you, all your servers have Powershell installed?

Grant Ward, a.k.a. Bigteddy

What's new in Powershell 3.0 (Technet Wiki)


Tuesday, March 6, 2012 7:55 PM

don’t yours?

 

 

Justin Rich
http://jrich523.wordpress.com
PowerShell V3 Guide (Technet)
Please remember to mark the replies as answers if they help and unmark them if they provide no help.


Tuesday, March 6, 2012 7:56 PM

So if I understand you, all your servers have Powershell installed?

Grant Ward, a.k.a. Bigteddy

What's new in Powershell 3.0 (Technet Wiki)

No, but that doesn't really matter. I'll only be running PS scripts on systems that have PS installed. Tivoli will be handling the targeting of the correct systems. Then the Tivoli agent on each system is what will actually be executing the scripts.

so at this point, I really just need to know if it's possible that when the agent executes, say this: 
powershell.exe -NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy unrestricted -File ".\someScript.ps1"

is it 'possible' that a 64bit windows OS would start the 32bit version of powershell.exe rather than what it would normally do by default, which is start the 64bit version of powershell.exe? If you can't configure the OS to only run 32bit .net, then I think I should be good to go with Paulo's method. Otherwise I'll use Win32_Processor's AddressWidth property.


Tuesday, March 6, 2012 7:57 PM

Not just the servers.  All the workstations too, (XP upwards), with remoting enabled.  What a pleasure to administrate!

Grant Ward, a.k.a. Bigteddy

What's new in Powershell 3.0 (Technet Wiki)


Tuesday, March 6, 2012 9:12 PM

oh man... that is the case here. I'll need to test to confirm, but the agent *is* 32bit.

thank you jrich! That could decide this for me... I'll post back.


Tuesday, March 6, 2012 9:29 PM | 1 vote

You're right to be cautionous.

IntPtr.Size will actually report if the process is 32-bit or 64-bit.

This is code I actually am using to configure the registry for a 32-bit application, regardless of it's a 32 or 64 bit Powershell console:

if ([System.IntPtr]::Size -eq 8) {    $RegistryRoot = 'HKLM:\SOFTWARE\Wow6432Node\MyApp'}else {    $RegistryRoot = 'HKLM:\SOFTWARE\MyApp'}

Paulo Morgado


Tuesday, March 6, 2012 9:55 PM

My 64-bit Windows OS shows 8 as the value of [System.IntPtr]::Size

   - Larry

  >

 >

On 3/6/2012 12:17 PM, Paulo Morgado [MVP] wrote:

> Powershell is built on top of the .NET Framework.

>

> In the .NET Framework, the IntPtr structure

 > represents a pointer or handle in the underlying operating system.

 > And it has a Size property

> Just check if it's 4 or 9 bites long.

>

> Assuming only 32-bit or 64-bit:

> if ([System.IntPtr]::Size -eq 4) {"32-bit"  } else {"64-bit"  }

>

 


Tuesday, March 6, 2012 10:01 PM

Of courese it does. The 9 was a typo.

But it will show 4 on the x86 console.

Paulo Morgado


Tuesday, March 6, 2012 10:51 PM

Thanks all for the input, I appreciate it.

I confirmed that the Tivoli agent is a 32bit process, and thus it executes the 32bit version of powershell. So this would lead to [System.IntPtr]::Size reporting 32-bit even on my 64bit systems. As Paulo already said, this tells us if the 'process' is 64 or 32 bit. So my case is a peculiar circumstance that makes this very elegant solution not an option for me. However I will certainly be using it for other cases, as its a great way to concisely get this information... and the more 'typical' scenario (when a 32 bit agent is not launching your script for you, forcing it to 32bit version of PS) would be a user executing the script and it would work great for that... or in remoting cases. Even though I can't use for my scenario I'll be marking as an answer. Thank you Paulo. 

Thank you jrich for catching that one (the fact that if the agent is 32bit and it starts powershell, it will start the 32bit version of powershell)!

I will use the method I have been using, which I know works. It's my own function that first determines if it's running on server 2003 or 2008 and uses the methods that work for them. For 2003, I parse the Win32_OperatingSystem.Caption property for 'x64', if it's there, it's 64bit, if not, it's 32bit. For 2008 and newer I use Win32_OperatingSystem.OSArchitecture. I'll stick with this method for my Tivoli agent based scenario.

Thanks again all!


Wednesday, March 7, 2012 6:17 AM

I'd just like to say, well done, for exploring all the possibilities, and seeing the possible pitfalls of each.  In the end you came back to your original code, but you certainly did a thorough investigation of other options!

Grant Ward, a.k.a. Bigteddy

What's new in Powershell 3.0 (Technet Wiki)


Friday, January 9, 2015 7:33 AM

According to the question, that's not right.

The IntPtr size of a 32-bit Process on a 64-bit OS is still 4.

It's not possible to detect the OS-architecture with the IntPtr. You can only detect the Bit-Architecture of the current Process.


Friday, May 22, 2015 9:26 AM

Using PowerShell and SystemInfo:

systeminfo | Where-Object { $_.Contains("System Type") }

Result may be:
System Type:               X86-based PC
or
System Type:               x64-based PC

PS C:\Windows\system32> $bitVersion = (systeminfo | Where-Object { $_.Contains("System Type") }).Substring(28, 2)
PS C:\Windows\system32> $bitVersion
64


Wednesday, August 10, 2016 9:51 AM

Powershell is built on top of the .NET Framework.

In the .NET Framework, the IntPtr structure represents a pointer or handle in the underlying operating system. And it has a Size property. Just check if it's 4 or 9 bites long.

Assuming only 32-bit or 64-bit:

if ([System.IntPtr]::Size -eq 4) { "32-bit" } else { "64-bit" }

Paulo Morgado

Thank you, this works in Windows 7 under powershell 2, I tried using [system.environment]::Is64BitOperatingSystem but it was introduced in powershell 3.

DG


Friday, August 3, 2018 1:46 PM

$bittness = [environment]::Is64BitOperatingSystem 
if($bittness -eq "True")
{
write-host "system is 64 bit"
}else{
write-host " system is 32 bit"
}

Friday, August 3, 2018 3:25 PM

test-path 'C:\Program Files (x86)\


Monday, November 11, 2019 11:04 PM

This will only show you the environment variable based how PowerShell is being ran.  If you use the 32-bit ISE versus the 64-bit ISE you will return the response for the environment, thus giving you a false positive of a 32-bit OS if you run the command through the 32-bit PowerShell interpreter on a 64-bit system.  Because of this you will want to stay away from the Pointer size or $env:PROCESSOR_ARCHITECTURE.

The following will return either 32-bit or 64-bit relative to the OS regardless of the interpreter environment:  

(Get-WMIObject Win32_OperatingSystem).OSArchitecture OR 

(Get-CIMInstance CIM_OperatingSystem).OSArchitecture 

WMI commands can be ran from the CMD line or PS CMD line, so you can also do:

WMIC OS get OSarchitecture

-- Octavian Düm MCP Windows XP


Monday, November 11, 2019 11:55 PM

This will only show you the environment variable based how PowerShell is being ran.  If you use the 32-bit ISE versus the 64-bit ISE you will return the response for the environment, thus giving you a false positive of a 32-bit OS if you run the command through the 32-bit PowerShell interpreter on a 64-bit system.  Because of this you will want to stay away from the Pointer size or $env:PROCESSOR_ARCHITECTURE.

The following will return either 32-bit or 64-bit relative to the OS regardless of the interpreter environment:  

(Get-WMIObject Win32_OperatingSystem).OSArchitecture OR 

(Get-CIMInstance CIM_OperatingSystem).OSArchitecture 

WMI commands can be ran from the CMD line or PS CMD line, so you can also do:

WMIC OS get OSarchitecture

-- Octavian Düm MCP Windows XP

Why>

This does the job quickly and easily:

[environment]::Is64BitOperatingSystem

or in batch:

echo %PROCESSOR_ARCHITECTURE%

\(ツ)_/