プログラマメモ2 - programmer no memo2

javaからMacアドレス ~ Windows編 2008/07/17
2008/07/22

Javaです。
Windowsです。JavaからMACアドレスの取得についてです。

現時点で思いつくであろう方法は3種類です。
(A)OS付属のコマンドをexecして、パスして取得
(B)Java6を使う
(C)JNIを使ってLibから取得

ベストなのは(B)だと思います。


Java6が使えない環境は、残念ながら(A),(C)ですかね。
Javaだといいつつ、Windows専用アプリを開発してたりのですが、どうもWindowsOSのバージョン(XP、VISTA)でipconfigが返してくれる文字列違ったりしたので、深く追求せず、(C)を採用することにしました。

すでに試みている人がいたので
そのまんまコードを参考にしつつ。

もうここ数年C,C++使っていなかったので、思い出しつつ。
コンパイル環境は、WindowsXPで、BorlandのBCC55を使いました。

ボーランドのコンパイラの使い方は、Borland C++ Compiler 5.5日本語版のインストールの方法が参考になりました。

JNIを使っての開発はここがJavaでHello World JNI編いい感じですね。あとここもcivic site : JNIを使ってみる

javahを使ってごにょごにょと。

その他、WindowsでのMacアドレス取得のための参考

で、僕が一番はまったのは、bcc32のリンカの動作というかコンパイルしてオブジェクト作ったあとのための処理でした。

bcc32を使って、下記のようなエラーがでました。
Error: 外部シンボル 'GetIfTable' が未解決


それで、下記のサイトでの説明が、しっくり。
C入門14

bcc32 -I"C:\Program Files\Java\jdk1.6.0\include" -I"C:\Program Files\Java\jdk1.6.0\include\win32" -tWD GetMacAddress.cpp C:\borland\bcc55\Lib\PSDK\iphlpapi.lib


リブを最後に指定してあげて解決。

以下コードです。

気まぐれなる日々さんのそのまんまだったりしかすが....

Java
class GetMacAddress {
static {
System.loadLibrary("GetMacAddress");
}
public native String getMacAddress();
}


ネイティブコード(Win32)
#include <windows.h>
#include <iphlpapi.h>
#include "GetMacAddress.h"

JNIEXPORT jstring JNICALL Java_GetMacAddress_getMacAddress
(JNIEnv *env, jobject obj) {

char buf[1024];
DWORD d=0 ;

GetIfTable( NULL , &d, FALSE );

PMIB_IFTABLE IfTable = (PMIB_IFTABLE)new char[d] ;

if( IfTable ){
if( GetIfTable( (PMIB_IFTABLE)IfTable,&d,FALSE) == NO_ERROR ){
wsprintf(buf,"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x"
,(unsigned char)IfTable->table[0].bPhysAddr[0]
,(unsigned char)IfTable->table[0].bPhysAddr[1]
,(unsigned char)IfTable->table[0].bPhysAddr[2]
,(unsigned char)IfTable->table[0].bPhysAddr[3]
,(unsigned char)IfTable->table[0].bPhysAddr[4]
,(unsigned char)IfTable->table[0].bPhysAddr[5]
);
}
}

return env->NewStringUTF(buf);
}



※Javaを使っているのに、Linux、MacOSで動作させることを頭から放棄するのも気概がないというか、センスがないというか残念な話なのですが。

2008-07-22
ふと検索かけたら、自分のブログが検索にひっかかった。
書いたの2年前なんですよね。その間、お仕事で新しいことしていない....Orz...

あと、どうもXP,Vistaで違いがあるようです。

もしかして、取得した値がイーサネットかどうかという判断をさせる必要があるかもしれませんね。ふぅ。

というわけで上記のOKWaveを参考にして、typeとspeedを使ってイーサネットを判断?させてみました。手元の環境では、XP,vistaでうまくいっているようにみえますが、いろいろな環境でためさないと確信できませんね。

とても参考になったサイトは、ここです。

JNIEXPORT jstring JNICALL Java_GetMacAddress_getMacAddress
(JNIEnv *env, jobject obj) {

char buf[1024];
DWORD d=0 ;

GetIfTable( NULL , &d, FALSE );

PMIB_IFTABLE IfTable = (PMIB_IFTABLE)new char[d];

if( IfTable ){
if( GetIfTable( (PMIB_IFTABLE)IfTable,&d,FALSE) == NO_ERROR ){
for(int i=0;i< (int)IfTable->dwNumEntries;i++ ){
int type = (int)IfTable->table[i].dwType;
int speed = (int)IfTable->table[i].dwSpeed;
if( type == 6
&& (10000000000 == speed
|| 1000000000 == speed
|| 100000000 == speed )){
wsprintf(buf,"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x"
,(unsigned char)IfTable->table[i].bPhysAddr[0]
,(unsigned char)IfTable->table[i].bPhysAddr[1]
,(unsigned char)IfTable->table[i].bPhysAddr[2]
,(unsigned char)IfTable->table[i].bPhysAddr[3]
,(unsigned char)IfTable->table[i].bPhysAddr[4]
,(unsigned char)IfTable->table[i].bPhysAddr[5]
);
break;
}
}
}
delete [] IfTable;
}

return env->NewStringUTF(buf);
}

: