前回は32ビット環境、今回は64ビット環境でVisualBasicからアンマネージド関数を呼び出してみる事に。
マイクロソフトのGetSystemInfo関数のドキュメントに、
To retrieve accurate information for an application running on WOW64, call the GetNativeSystemInfo function.
とあったので、GetNativeSystemInfo関数を呼び出すだけのサンプルを作ってみました。
★凡そ10年前の Windows7 は当然、現役のバリバリ。
それはさて置き、前回作成の32ビット版だと思っていたプログラムが、WOW64下(?)で思いがけない動作結果に。
CPUタイプなど、一部不確かなデータを拾ってきてしまいます。試しに Windows7 64Bit 版でもプログラムを作成・実行してみると、同様の結果に。
調べてみると、初期設定(インストール時)のままのIDEでは、Visual Basic は実行対象OSが 32bit/64bit のどちらのバージョンでも、ネイティブ動作するようにコンパイルするようです。
マイクロソフトドキュメント ⇒ 任意のプラットフォーム上で実行されるように、アセンブリをコンパイルします。アプリケーションは、Windowsの32ビットバージョンでは32ビットアプリケーションとして、Windowsの64ビットバージョンでは64ビットアプリケーションとして実行されます。この anycpu フラグが既定値です。
★例え32ビットのOS上でコンパイルしても、上記の動作をするのには驚きだわ! 各.NET開発言語によって作成される中間言語(MSIL)は、CPUや各Windowsプラットフォームに依存しないコードになっていて、実行される際に順次ネイティブコードにコンパイルされます(=JITコンパイラだそうな)。
・と言う訳で、規定値設定のVisualBasicで作成された実行ファイル(exe)は、WOW64配下には入らず64ビットCLR上で動作します。
・なので、以下の3メンバーを ULong に直してやれば構造体サイズには不満は残るけど、それなりの動作結果に。
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
・自分的には、ムズイ。意識していないと、多分ど壺に嵌るな、きっと。
<注意点>
・Win64 ではC/C++のポインタサイズは8バイト、ポインタ精度変数のサイズも8バイト。つまり、Long 型です。
・DWORD_PTR も Win64 では8バイトで Long 型。LPVOID は IntPtr の方が好ましい?
・Visual Basic のデフォルトの文字セットは、UNICODE です。
お試し環境
WindowsXP 32bit Edition、Windows7 64bit Edition
Visual Basic 2008
/*-------------------------------- お試し結果 ------------------------------*/
・GetNativeSystemInfo 関数の取得データ
・GetSystemInfo 関数の取得データ
/*----------------------------------------------------------------------------*/
/*-------------------------------- お試しソース ----------------------------*/
Imports System.Runtime.InteropServices
Public Class Form4
Const PROCESSOR_ARCHITECTURE_INTEL As Integer = 0 ' x86
Const PROCESSOR_ARCHITECTURE_ARM As Integer = 5 ' ARM
Const PROCESSOR_ARCHITECTURE_IA64 As Integer = 6 ' Intel Itanium-based
Const PROCESSOR_ARCHITECTURE_AMD64 As Integer = 9 ' x64(AMD or Intel)
Const PROCESSOR_ARCHITECTURE_ARM64 As Integer = 12 ' ARM64
Const PROCESSOR_ARCHITECTURE_UNKNOWN As Integer = &HFFFF ' Unknown architecture
Const PROCESSOR_INTEL_386 As Integer = 386
Const PROCESSOR_INTEL_486 As Integer = 486
Const PROCESSOR_INTEL_PENTIUM As Integer = 586
Const PROCESSOR_INTEL_IA64 As Integer = 2200
Const PROCESSOR_AMD_X8664 As Integer = 8664
' Const PROCESSOR_ARM As Integer = Reserved
Structure SYSTEM_INFO
Dim wProcessorArchitecture As UShort
Dim wReserved As UShort
Dim dwPageSize As UInteger
Dim lpMinimumApplicationAddress As ULong
Dim lpMaximumApplicationAddress As ULong
Dim dwActiveProcessorMask As ULong
Dim dwNumberOfProcessors As UInteger
Dim dwProcessorType As UInteger
Dim dwAllocationGranularity As UInteger
Dim wProcessorLevel As UShort
Dim wProcessorRevision As UShort
End Structure
Structure SYSTEM_INFO2
Dim wProcessorArchitecture As UShort
Dim wReserved As UShort
Dim dwPageSize As UInteger
Dim lpMinimumApplicationAddress As IntPtr
Dim lpMaximumApplicationAddress As IntPtr
Dim dwActiveProcessorMask As ULong
Dim dwNumberOfProcessors As UInteger
Dim dwProcessorType As UInteger
Dim dwAllocationGranularity As UInteger
Dim wProcessorLevel As UShort
Dim wProcessorRevision As UShort
End Structure
Declare Auto Sub GNSInfo Lib "kernel32.dll" Alias "GetNativeSystemInfo" (ByRef sysInfo As SYSTEM_INFO)
Declare Auto Sub GSInfo Lib "kernel32.dll" Alias "GetSystemInfo" (ByRef sysInfo As SYSTEM_INFO2)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim sInfo As SYSTEM_INFO
Dim sInfo2 As SYSTEM_INFO2
Dim msg1, msg2 As String
GNSInfo(sInfo)
GSInfo(sInfo2)
msg1 = "wProcessorArchitecture = " & sInfo.wProcessorArchitecture & vbCrLf & _
"wReserved = " & sInfo.wReserved & vbCrLf & _
"dwPageSize = " & sInfo.dwPageSize & vbCrLf & _
"lpMinimumApplicationAddress = " & sInfo.lpMinimumApplicationAddress.ToString("x") & vbCrLf & _
"lpMaximumApplicationAddress = " & sInfo.lpMaximumApplicationAddress.ToString("x") & vbCrLf & _
"dwActiveProcessorMask = " & sInfo.dwActiveProcessorMask & vbCrLf & _
"dwNumberOfProcessors = " & sInfo.dwNumberOfProcessors & vbCrLf & _
"dwProcessorType = " & sInfo.dwProcessorType & vbCrLf & _
"dwAllocationGranularity = " & sInfo.dwAllocationGranularity & vbCrLf & _
"wProcessorLevel = " & sInfo.wProcessorLevel & vbCrLf & _
"wProcessorRevision = " & sInfo.wProcessorRevision
msg2 = "wProcessorArchitecture = " & sInfo2.wProcessorArchitecture & vbCrLf & _
"wReserved = " & sInfo2.wReserved & vbCrLf & _
"dwPageSize = " & sInfo2.dwPageSize & vbCrLf & _
"lpMinimumApplicationAddress = " & sInfo2.lpMinimumApplicationAddress.ToString("x") & vbCrLf & _
"lpMaximumApplicationAddress = " & sInfo2.lpMaximumApplicationAddress.ToString("x") & vbCrLf & _
"dwActiveProcessorMask = " & sInfo2.dwActiveProcessorMask & vbCrLf & _
"dwNumberOfProcessors = " & sInfo2.dwNumberOfProcessors & vbCrLf & _
"dwProcessorType = " & sInfo2.dwProcessorType & vbCrLf & _
"dwAllocationGranularity = " & sInfo2.dwAllocationGranularity & vbCrLf & _
"wProcessorLevel = " & sInfo2.wProcessorLevel & vbCrLf & _
"wProcessorRevision = " & sInfo2.wProcessorRevision
MessageBox.Show(msg1, "SYSTEM_INFO arg data")
MessageBox.Show(msg2, "SYSTEM_INFO2 arg data")
Select Case sInfo.wProcessorArchitecture
Case PROCESSOR_ARCHITECTURE_INTEL
MessageBox.Show("32ビット", "OSのタイプ")
Case PROCESSOR_ARCHITECTURE_ARM
Case PROCESSOR_ARCHITECTURE_IA64
Case PROCESSOR_ARCHITECTURE_AMD64
MessageBox.Show("64ビット", "OSのタイプ", MessageBoxButtons.OK, MessageBoxIcon.Information)
Case PROCESSOR_ARCHITECTURE_ARM64
Case PROCESSOR_ARCHITECTURE_UNKNOWN
End Select
Select Case sInfo.dwProcessorType
Case PROCESSOR_INTEL_386
Case PROCESSOR_INTEL_486
Case PROCESSOR_INTEL_PENTIUM
MessageBox.Show("Pentium4", "CPUのタイプ")
Case PROCESSOR_INTEL_IA64
Case PROCESSOR_AMD_X8664
MessageBox.Show("AMD Ryzen?" & vbCrLf & "な訳ありません", "CPUのタイプ", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Select
MessageBox.Show(sInfo.dwNumberOfProcessors & " Core", "プロセッサ数", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
End Class
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*============================================================================*/