The test I did with BinaryReader with help of AI (click on a Button, change sPath variable) =>
Imports System.IO
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Test C# or VB.NET app
Dim sPath As String = "E:\Sources\CSharp_Test5\bin\Debug\CSharp_Test5.exe"
'Dim sPath As String = "E:\Sources\VB_ReadPE\bin\x86\Debug\VB_ReadPE.exe"
System.Diagnostics.Debug.WriteLine($"Executable : {sPath}")
Dim nCpuType = AssemblyCpuChecker.GetCpuType(sPath)
System.Diagnostics.Debug.WriteLine($"Target : {nCpuType}")
End Sub
End Class
Public Class AssemblyCpuChecker
' https//sushihangover.github.io/ms-corflags-showing-incorrect-flags/
' CorFlags
' Developer Command Prompt for VS 2022
' E:\Program Files\Microsoft Visual Studio\2022\Enterprise>CorFlags "E:\Sources\CSharp_Test5\bin\Debug\CSharp_Test5.exe"
'Version: v4.0.30319
'CLR Header : 2.5
'PE: PE32
'CorFlags: 0x20003
'ILONLY: 1
'32BITREQ : 0
'32BITPREF : 1
'Signed: 0
Public Const COMIMAGE_FLAGS_ILONLY As Integer = &H1
Public Const COMIMAGE_FLAGS_32BITREQUIRED As Integer = &H2
Public Const COMIMAGE_FLAGS_IL_LIBRARY As Integer = &H4
Public Const COMIMAGE_FLAGS_STRONGNAMESIGNED As Integer = &H8
Public Const COMIMAGE_FLAGS_NATIVE_ENTRYPOINT As Integer = &H10
Public Const COMIMAGE_FLAGS_TRACKDEBUGDATA As Integer = &H10000
Public Const COMIMAGE_FLAGS_32BITPREFERRED As Integer = &H20000
Public Enum CpuType
Unknown
x86
x64
AnyCPU
AnyCPU_Prefer32Bit
End Enum
' Some parts generated with Copilot + ChatGPT, then fixed...
Public Shared Function GetCpuType(filePath As String) As CpuType
Using fs As New FileStream(filePath, FileMode.Open, FileAccess.Read)
Using br As New BinaryReader(fs)
fs.Seek(&H3C, SeekOrigin.Begin)
Dim nPEHeaderOffset As Integer = br.ReadInt32()
fs.Seek(nPEHeaderOffset + 4, SeekOrigin.Begin) ' Skip "PE\0\0"
Dim nMachine As UShort = br.ReadUInt16()
Dim nNumberOfSections As UShort = br.ReadUInt16()
fs.Seek(16, SeekOrigin.Current) ' skip rest of COFF header
Dim nOptionalHeaderStart As Long = fs.Position
Dim nOptionalHeaderMagic As UShort = br.ReadUInt16()
Dim bPE32 As Boolean = (nOptionalHeaderMagic = &H10B)
Dim nDataDirectoryOffset As Integer = If(bPE32, &H60 + 8 * 14, &H70 + 8 * 14)
Dim nCLRDirOffset As Long = nOptionalHeaderStart + nDataDirectoryOffset
fs.Seek(nCLRDirOffset, SeekOrigin.Begin)
Dim nCLRHeaderRVA As UInteger = br.ReadUInt32()
Dim nCLRHeaderSize As UInteger = br.ReadUInt32()
If nCLRHeaderRVA = 0 Then
Return CpuType.Unknown ' Not a .NET assembly
End If
' Section table comes after optional header
Dim nOptionalHeaderSize As Integer = If(bPE32, 224, 240)
Dim nSectionTableStart As Long = nOptionalHeaderStart + nOptionalHeaderSize
Dim nCLRHeaderFileOffset As UInteger = 0
For i As Integer = 0 To nNumberOfSections - 1
fs.Seek(nSectionTableStart + i * 40 + 8, SeekOrigin.Begin)
Dim nVirtualSize As UInteger = br.ReadUInt32()
Dim nVirtualAddress As UInteger = br.ReadUInt32()
Dim nSizeOfRawData As UInteger = br.ReadUInt32()
Dim nPointerToRawData As UInteger = br.ReadUInt32()
Dim nSectionSize As UInteger = Math.Max(nVirtualSize, nSizeOfRawData)
If nCLRHeaderRVA >= nVirtualAddress AndAlso nCLRHeaderRVA < nVirtualAddress + nSectionSize Then
nCLRHeaderFileOffset = nPointerToRawData + (nCLRHeaderRVA - nVirtualAddress)
Exit For
End If
Next
If nCLRHeaderFileOffset = 0 Then
Return CpuType.Unknown
End If
fs.Seek(nCLRHeaderFileOffset + 16, SeekOrigin.Begin)
Dim nCorFlags As UInteger = br.ReadUInt32()
' 131075 = 0x20003
System.Diagnostics.Debug.WriteLine($"CorFlags : 0x{nCorFlags:X} ({nCorFlags})")
System.Diagnostics.Debug.WriteLine($"ILONLY : {((nCorFlags And COMIMAGE_FLAGS_ILONLY) <> 0)}")
System.Diagnostics.Debug.WriteLine($"32BITREQUIRED : {((nCorFlags And COMIMAGE_FLAGS_32BITREQUIRED) <> 0)}")
System.Diagnostics.Debug.WriteLine($"32BITPREFERRED : {((nCorFlags And COMIMAGE_FLAGS_32BITPREFERRED) <> 0)}")
System.Diagnostics.Debug.WriteLine($"Machine : 0x{nMachine:X}")
If (nCorFlags And COMIMAGE_FLAGS_32BITPREFERRED) <> 0 Then
Return CpuType.AnyCPU_Prefer32Bit
End If
If (nCorFlags And COMIMAGE_FLAGS_32BITREQUIRED) <> 0 Then
Return CpuType.x86
End If
If (nMachine = &H8664) Then
Return CpuType.x64
End If
If (nCorFlags And COMIMAGE_FLAGS_ILONLY) <> 0 Then
Return CpuType.AnyCPU
End If
Return CpuType.Unknown
End Using
End Using
End Function
End Class