微禄: 2021年10月アーカイブ

Windowsでは同一プロセス内に、32ビットプログラムと64ビットプログラムの混在は許されていません。例えば、32ビット動作のプログラムをx86、64ビット動作のプログラムをx64とした場合、

OK:x86のExeとx86のDLL *1、x64のExeとx64のDLL *2 は呼出し可能
NG:x86のExeとx64のDLL、  x64のExeとx86のDLLは呼出し不可

 *1:32ビットOS または Wow64配下で動作
 *2:64ビットOSのみで動作

ですので、ネイティブ動作指向のVisualBasicでは IsWow64Process 関数とは無縁だよなぁ~と思ってしまいましたが、前回、既定値の「AnyCPU」を「x86」に変更した事もあり、使ってみる事に。

マイクロソフトのドキュメントによれば、GetCurrentProcess関数とIsWow64Process関数の構文は、

■ Retrieves a pseudo handle for the current process.

HANDLE GetCurrentProcess();

Return value
The return value is a pseudo handle to the current process.

■ Determines whether the specified process is running under WOW64 or an Intel64 of x64 processor.

BOOL IsWow64Process(HANDLE hProcess, PBOOL Wow64Process);

Return value
If the function succeeds, the return value is a nonzero value.
If the function fails, the return value is zero. To get extended error information, call GetLastError.

なので、戻り値と引数の変数型を Integer と Boolean に置き換えれば、上手くゆく筈?

とは言うものの、一筋縄では行かないのはBOOLでしょうか。

マイクロソフトのドキュメントによれば、

・C/C++では、BOOL は int 型、BOOLEAN は BYTE 型の様です(TRUE または FALSE である必要があります)。

・VBでは、以下様なのだとか。

Boolean 型が数値型に正確に変換されない

Boolean データ型の値は数値として格納されず、格納された値は数値と等価であると見なされません。以前のバージョンとの互換性のために、Visual Basic は変換キーワード (CType 関数、CBool、CInt など) を使用して、Boolean と数値型の間で変換を行います。ただし、その他の言語では、.NET Framework メソッドと同様に、これらの変換が異なる方法で実行されることがあります。

True と False に対して等価の数値に依存するコードを記述することは避けてください。可能な限り、Boolean 変数には、仕様で定められている論理値以外の値を使用しないようにしてください。Boolean 値と数値を混在させる必要がある場合は、選択する変換方法をよく理解してください。

Visual Basic での変換

CType または CBool の変換キーワードを使用して数値データ型を Boolean に変換するとき、0 が False になり、その他のすべての値が True になります。変換キーワードを使用して Boolean 値を数値型に変換するとき、False は 0 になり、True は -1 になります。


<注意点>

・C/C++では、HANDLE は PVOID 型です。(AnyCPU では Integer ではなく IntPtr で)

・VBの Boolean 変数は サイズが2バイトらしいので、偶々、動作している可能性大。

・不測の事態を招かないために、IsWow64Process 関数の戻り値は失敗したかどうか、つまり"0"かどうかをチェックするのが宜しいかと。

・VisualStudio11と.NET4.5でマイクロソフトがAnyCPUを再定義したそうな
 新たなデフォルトは、「AnyCPU32Bit優先」らしい。(何周遅れ? の気付き)
 ⇒これは動作が可能な場合、32Bitで動作する。という事らしい。


お試し環境
  WindowsXP 32bit Edition、Windows7 64bit Edition
  Visual Basic 2008 対象CPUはx86とAnyCPU


/*-------------------------------- お試し結果 ------------------------------*/

・敢えて、x86版を WindowsXP 32bit Edition で動作させてみる

x86 版 WindowsXP 32bit Edition で動作

・x86版を Windows7 64bit Edition で動作

x86 版 Windows7 64bit Edition で動作

・AnyCPU版を Windows7 64bit Edition で動作

AnyCPU 版 Windows7 64bit Edition で動作

/*----------------------------------------------------------------------------*/


/*-------------------------------- お試しソース ----------------------------*/

Public Class Form1

    Declare Auto Function GetCurrentProcess Lib "kernel32" () As Integer
    Declare Auto Function IsWow64Process Lib "kernel32" (ByVal hprcs As Integer, ByRef w64prcs As Boolean) As Boolean

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim hdl As Integer
        Dim res As Boolean
        Dim biw64 As Boolean
        Dim msg As String

        hdl = GetCurrentProcess
        res = IsWow64Process(hdl, biw64)
        If res <> 0 Then
            msg = "return GetCurrentProcess : " & hdl.ToString & vbCrLf & _
                  "return IsWow64Process : " & res & vbCrLf & _
                  "Wow64Process value : " & biw64

            MsgBox(msg, MsgBoxStyle.Information, "result IsRunningUnderWow64")
        Else
            MsgBox(Err.LastDllError, MsgBoxStyle.AbortRetryIgnore, "IsWow64Process Error Occured")
        End If
    End Sub
End Class

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*============================================================================*/

前回、VBコンパイラが規定値の"任意のCPU"設定だった事もあり、Windows7でもネイティブ(64ビット)動作となってしまいましたので、今一だったなぁ~と。

そこでWindowsXPのVisualBasicは、32ビットでコンパイルする様にIDEの設定を変更してみました。

マイクロソフトのドキュメントによると、

・構成マネージャーを使用して、対象プラットフォームを指定
・プロジェクトのプロパティを使用して、対象CPUを指定

などが有るようですが、構成マージャーには新規作成や編集などの作業が必須の様なので、面倒くさがり屋には不向きです。という事で、プロジェクトのプロパティを使用して、対象CPUを指定してみる事に。

・メニューバーの「プロジェクト」をクリック→プルダウンメニューの「(プロジェクト名)のプロパティ」を選択、または、
ソリューションエクスプローラの「プロジェクト名」を"右"クリック→プルダウンメニューの「プロパティ」を選択して、プロパティのダイアログを表示します。


1.プロジェクトの「プロパティ」画面で、「コンパイル」を選択し、「詳細コンパイルオプション」ボタンをクリック

VBプロジェクトのプロパティ画面


2.「コンパイラの詳細設定」画面で、「ターゲットCPU」の内容を確認

コンパイラの詳細設定画面で内容確認

・32ビットでコンパイル出来る様に、「AnyCPU」を「x86」に変更します


3.「コンパイラの詳細設定」画面で、「ターゲットCPU」の変更内容を確認

コンパイラの詳細設定画面で内容変更


コンパイラの対象CPU指定をx86に変更して Windows7 64Bit 版で動作確認したところ、WOW64配下で動作する事を確認できました。
2つの関数の取得データには、wProcessorArchitecture/lpMaximumApplicationAddress/dwProcessorType に違いがみられました。

・やはりCPU情報を詳しく知りたい場合には、GetNativeSystemInfo 関数の方が優れているようです。


お試し環境
  WindowsXP 32bit Edition、Windows7 64bit Edition
  Visual Basic 2008 対象CPUはx86


/*-------------------------------- お試し結果 ------------------------------*/

・GetSystemInfo 関数の取得データ

WOW64下 GetSystemInfo 関数の取得データ

・GetNativeSystemInfo 関数の取得データ

WOW64下 GetNativeSystemInfo 関数の取得データ

/*----------------------------------------------------------------------------*/


/*-------------------------------- お試しソース ----------------------------*/

前々回の「32ビットOS下のVisualBasicからGetSystemInfo関数を呼び出す」記事のソースと同じです。

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*============================================================================*/