2

#PSTip How to determine if a file is 32-bit or 64-bit

Someone at the office asked me to check why a specific file was failing to execute. When double-clicking the file, nothing happened and no related process could be found in Task Manager. To cut the long story short, we found that the issue was probably running the file on a 32-bit machine while the file was written for x64 platforms.  Anyway, we wanted to verify that and I was looking for a way to do that with PowerShell. After a short web search I found this StackOverflow thread.

Here’s the translated version of the suggested C# code. It sure verified our suspicion–the failing  file was written for x64 platforms. Here’s a test against notepad.exe.

$MACHINE_OFFSET = 4
$PE_POINTER_OFFSET = 60
$MachineType = Write-Output Native I386 Itanium x64

$filePath = "$env:windir\notepad.exe"
$data = New-Object System.Byte[] 4096
$stream = New-Object System.IO.FileStream -ArgumentList $filePath,Open,Read
$stream.Read($data,0,$PE_POINTER_OFFSET) | Out-Null
$PE_HEADER_ADDR = [System.BitConverter]::ToInt32($data, $PE_POINTER_OFFSET)
$machineUint = [System.BitConverter]::ToUInt16($data, $PE_HEADER_ADDR + $MACHINE_OFFSET)
$MachineType[$machineUint]
Filed in: Columns, Tips and Tricks Tags: ,

2 Responses to "#PSTip How to determine if a file is 32-bit or 64-bit"

  1. On my x86 system:

    PS Z:> $MachineType[$machineUint]
    x64

    http://www.pinvoke.net/default.aspx/kernel32.getbinarytype

    PS Z:> Get-BinaryType “$env:windirnotepad.exe”
    BIT32

  2. mmashwani says:

    The code in this blog post does not work. I have made the appropriate fixes below:
    $filePath = “$env:windir\notepad.exe”

    [int32]$MACHINE_OFFSET = 4
    [int32]$PE_POINTER_OFFSET = 60

    [byte[]]$data = New-Object -TypeName System.Byte[] -ArgumentList 4096
    $stream = New-Object -TypeName System.IO.FileStream -ArgumentList ($filePath, ‘Open’, ‘Read’)
    $stream.Read($data, 0, 4096) | Out-Null

    [int32]$PE_HEADER_ADDR = [System.BitConverter]::ToInt32($data, $PE_POINTER_OFFSET)
    [int32]$machineUint = [System.BitConverter]::ToUInt16($data, $PE_HEADER_ADDR + $MACHINE_OFFSET)
    switch ($machineUint) {
    0 { ‘Native’ }
    0x014c { ‘x86’ }
    0x0200 { ‘Itanium’ }
    0x8664 { ‘x64’ }
    }

Leave a Reply

Submit Comment

© 2016 PowerShell Magazine. All rights reserved. XHTML / CSS Valid.
Proudly designed by Theme Junkie.
%d bloggers like this: