x86、x64、および IA64 用に作成された Windows 実行可能ファイルを使用する必要があります。ファイル自体を調べて、プログラムでプラットフォームを把握したいと思います。
私のターゲット言語は PowerShell ですが、C# の例で十分です。必要なロジックを知っていれば、それらのいずれかが失敗しても、それは素晴らしいことです。
x86、x64、および IA64 用に作成された Windows 実行可能ファイルを使用する必要があります。ファイル自体を調べて、プログラムでプラットフォームを把握したいと思います。
私のターゲット言語は PowerShell ですが、C# の例で十分です。必要なロジックを知っていれば、それらのいずれかが失敗しても、それは素晴らしいことです。
Visual Studio がインストールされている場合は、dumpbin.exe
. PowerShell Community Extensionsには、実行可能イメージのテストに使用できるGet-PEHeader
コマンドレットもあります。
Dumpbin は DLL を次のように報告しますmachine (x86)
。machine (x64)
Get-PEHeader は、DLL を次のいずれかとして報告しますPE32
。PE32+
GetBinaryType win32 関数が必要です。これにより、PE 形式の実行可能ファイルの関連部分が返されます。
通常、BinaryType フィールドには SCS_32BIT_BINARY または SCS_64BIT_BINARY のいずれかが表示されます。
または、PE 形式自体をチェックして、実行可能ファイルがコンパイルされているアーキテクチャを確認することもできます。
IMAGE_FILE_HEADER.Machine フィールドには、IA64 バイナリの場合は "IMAGE_FILE_MACHINE_IA64" が設定され、32 ビットの場合は IMAGE_FILE_MACHINE_I386、64 ビット (つまり x86_64) の場合は IMAGE_FILE_MACHINE_AMD64 が設定されます。
作業を進めるのに役立つMSDN マガジンの記事があります。
補遺:これはもう少し役立つかもしれません。バイナリをファイルとして読み取ります。最初の 2 バイトが「MZ」であることを確認し、次の 58 バイトをスキップして、60 バイトの魔法の 32 ビット値をイメージに読み取ります (PE 実行可能ファイルの場合は 0x00004550 に相当します)。次のバイトはこのヘッダーで、最初の 2 バイトはバイナリがどのマシン用に設計されているかを示します (0x8664 = x86_64、0x0200 = IA64、0x014c = i386)。
(エグゼクティブ サマリー: ファイルのバイト 65 と 66 を読み取り、イメージ タイプを取得します)
Assembly assembly = Assembly.LoadFile(Path.GetFullPath("ConsoleApplication1.exe"));
Module manifestModule = assembly.ManifestModule;
PortableExecutableKinds peKind;
ImageFileMachine machine;
manifestModule.GetPEKind(out peKind, out machine);
ターゲット マシンはマシン内にある必要があります。
ただし、これは .NET アセンブリでのみ機能します。
IMAGE_FILE_HEADER にアクセスするためのC# コードへのリンクを提供できます。これは (簡単に) PowerShell コマンドレットにコンパイルできると思います。ポインターと PInvoke 機能がないため、PowerShell スクリプトでそのメソッドを直接使用することはできないと確信しています。
ただし、PE ヘッダー形式に関する広範な知識を使用できるはずです ;-) 正しいバイトに「まっすぐ」進み、それを理解するだけです。これはPowerShell スクリプトで機能し、この C# コードを Tasos のブログからスクリプトに変換するだけでよいはずです。それは私のものではないので、ここでコードを繰り返す必要はありません。
Unix OS には、ファイルを識別する「file」というユーティリティがあります。識別するためのルールは、「magic」と呼ばれる記述ファイルに保持されます。file を試して、ファイルを正しく識別できるかどうかを確認し、マジック ファイルから適切なルールを取得できます。
ここでは、C での実装を示します。
// Determines if DLL is 32-bit or 64-bit.
#include <stdio.h>
int sGetDllType(const char *dll_name);
int main()
{
int ret;
const char *fname = "sample_32.dll";
//const char *fname = "sample_64.dll";
ret = sGetDllType(fname);
}
static int sGetDllType(const char *dll_name) {
const int PE_POINTER_OFFSET = 60;
const int MACHINE_TYPE_OFFSET = 4;
FILE *fp;
unsigned int ret = 0;
int peoffset;
unsigned short machine;
fp = fopen(dll_name, "rb");
unsigned char data[4096];
ret = fread(data, sizeof(char), 4096, fp);
fclose(fp);
if (ret == 0)
return -1;
if ( (data[0] == 'M') && (data[1] == 'Z') ) {
// Initial magic header is good
peoffset = data[PE_POINTER_OFFSET + 3];
peoffset = (peoffset << 8) + data[PE_POINTER_OFFSET + 2];
peoffset = (peoffset << 8) + data[PE_POINTER_OFFSET + 1];
peoffset = (peoffset << 8) + data[PE_POINTER_OFFSET];
// Check second header
if ((data[peoffset] == 'P') && (data[peoffset + 1] == 'E')) {
machine = data[peoffset + MACHINE_TYPE_OFFSET];
machine = (machine)+(data[peoffset + MACHINE_TYPE_OFFSET + 1] << 8);
if (machine == 0x014c)
return 32;
if (machine == 0x8664)
return 64;
return -1;
}
return -1;
}
else
return -1;
}