• ベストアンサー

GetAdapterInfoによりマックアドレスを取得したい。

はじめまして、sandayu999と申します。 ネットワークアダプタの情報を取得するために GetAdapterInfo関数を使用しているのですが 返り値がエラーとなってしまいます。 環境はWindowsXPでCコンパイラは borlandのbcc32.exeを使用しております。 コンパイルは正常に行えました。 [mac.c] --------------------------------------- IP_ADAPTER_INFO adapterInfo; DWORD aiSize; GetAdaptersInfo(NULL,&aiSize); //サイズ取得 print("%d\n",GetAdaptersInfo( &adapterInfo, &aiSize )); 出力してみたところ、値が87(ERROR_INVALID_PARAMETER) となってしまいました。 どのような対処をしたら良いのかわからない状態です、どなたかアドバイスをよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • hofuhofu
  • ベストアンサー率70% (336/476)
回答No.3

PIP_ADAPTER_INFO padapterInfo; DWORD aiSize; GetAdaptersInfo(NULL,&aiSize); padapterInfo=(PIP_ADAPTER_INFO)malloc(aiSize); printf("%d\n",GetAdaptersInfo( padapterInfo, &aiSize )); free(padapterInfo); でどうでしょう? 質問文のソースではアダプタが1つの時にしか正常に動作しないような気がします。

sandayu999
質問者

補足

hofuhofuさん、taka_tetsuさん返信ありがとうございます。 >taka_tetsuさん >書かれているコード、質問に書かれた部分で全部ですか? すみません、一部しか記述しておりませんでした。 全体は下記になります(多少みずらくなってます) ----------------- #include <windows.h> #include <iphlpapi.h> #include <stdio.h> void main(void){ IP_ADAPTER_INFO adapterInfo; DWORD aiSize, i; GetAdaptersInfo(NULL,&aiSize); if( GetAdaptersInfo( &adapterInfo, &aiSize ) != ERROR_SUCCESS ) { printf( "GetAdapterInfo呼び出し失敗\n" ); return; } fprintf( stdout,"MACアドレス = [" ); for( i = 0; i < adapterInfo.AddressLength; i++ ) { fprintf( stdout, "%.2X", (int)adapterInfo.Address[i] ); if( i == ( adapterInfo.AddressLength - 1 ) ) fputs( "]\n", stdout ); else fputs( "-", stdout ); } } そこで、hofuhofuさんのご指摘通りに行ってみたところ、 ----------------- PIP_ADAPTER_INFO padapterInfo; DWORD aiSize; GetAdaptersInfo(NULL,&aiSize); padapterInfo=(PIP_ADAPTER_INFO)malloc(aiSize); printf("%d\n",GetAdaptersInfo( padapterInfo, &aiSize )); free(padapterInfo); にて成功の0が出力されました。 これはIP_ADAPTER_INFOのポインタ型のPIP_ADAPTER_INFOを使用することでNIC分のメモリを 確保しているという解釈でよいでしょうか? (IP_ADAPTER_INFOだと、一つ分しか確保できていなかった) そこで、プログラムを下記のように直してみました。 ----------------- #include <windows.h> #include <iphlpapi.h> #include <stdio.h> void main(void){ PIP_ADAPTER_INFO padapterInfo; DWORD aiSize, i; GetAdaptersInfo(NULL,&aiSize); if( GetAdaptersInfo( padapterInfo, &aiSize ) != ERROR_SUCCESS ) { printf( "GetAdapterInfo呼び出し失敗\n" ); return; } while( padapterInfo ) { fprintf( stdout,"MACアドレス = [" ); for( i = 0; i < padapterInfo->AddressLength; i++ ) { fprintf( stdout, "%.2X", (int)padapterInfo->Address[i] ); if( i == ( padapterInfo->AddressLength - 1 ) ) fputs( "]\n", stdout ); else fputs( "-", stdout ); } padapterInfo = padapterInfo->Next; } free(padapterInfo); } [結果] ----------------- MACアドレス = [00-xx-xx-xx-xx-xx] MACアドレス = [00-xx-xx-xx-xx-xx] MACアドレス = [00-xx-xx-xx-xx-xx] と無事MACアドレスが出力されました。 雑誌にはもともとのソースでもNIC1枚分の情報は出力 されるとあったのですが、現在の方法 での処理のほうが正しいようです。 それと、MSDNのサンプルでは http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iphlp/iphlp/ip_adapter_info.asp でIP_ADAPTER_INFOのサンプルを見てみたのですが、 こちらはFREE関数を使ってメモリを最後に開放していないのですが、これはサンプルだから省略されたということでしょうか? 通常は、hohuhohuさんの書かれるとおり、最後にFREE を入れるべきですよね?

その他の回答 (5)

  • hofuhofu
  • ベストアンサー率70% (336/476)
回答No.6

ちょっと修正です。 aiSizeを初期化もせずにつかっているのがまずいです。 本来この手法はOutBufLenに0を指定して、強制的にERROR_BUFFER_OVERFLOWを起こし必要な領域のサイズを得ようというもののようです(このときpAdapterInfoは問題にならないのでNULLを入れている)。 MSDNのサンプルソースではアダプタが複数あった場合にのみ発生したERROR_BUFFER_OVERFLOWを処理しているのに対し、最初からERROR_BUFFER_OVERFLOWを前提にしてプログラムを組んでいるという違いがあります。 ただpAdapterInfoにNULLを指定した場合にもOutBufLenの値に関係なくERROR_BUFFER_OVERFLOWが発生し、OutBufLenに必要な領域のサイズが帰ってきているようです。 今回のケースではこの現象により正常に動いているように見えていたわけですが、MSDNにはERROR_BUFFER_OVERFLOWの発生条件としてOutBufLenが小さすぎること以外書かれていないので、この現象に依存したプログラムは避けるべきだと思います。

sandayu999
質問者

お礼

hohuhohuさん返信有難うございます。 なるほど、確かに自分のソースは最初からERROR_BUFFER_OVERFLOWをさせて取得しています。 (初期化もせずに) MSDNのソースに直した形での取得方法にしようと 思います。

  • hofuhofu
  • ベストアンサー率70% (336/476)
回答No.5

> これはIP_ADAPTER_INFOのポインタ型のPIP_ADAPTER_INFOを使用することでNIC分のメモリを > 確保しているという解釈でよいでしょうか? MSDNを見る限りそういうことだろうと判断して回答しました。 説明文を読むと十分な領域さえ確保されていれば、サイズはどのような値でもいいようです。 BYTE buf[5120]; DWORD aiSize=5120; GetAdaptersInfo((PIP_ADAPTER_INFO)buf,&aiSize); でもほとんどの環境で正常に動作すると思います。 それより改めて見直してみて気になったのは、 GetAdaptersInfo(NULL,&aiSize); //サイズ取得 ですね。 確かに必要な容量がaiSizeに帰ってきていますが、この挙動自体はMSDNに記載されていないようです。 If this size is insufficient to hold the adapter information, GetAdaptersInfo fills in this variable with the required size, and returns an error code of ERROR_BUFFER_OVERFLOW とはありますが、これはpOutBufLenで指定された値が必要な容量未満だったときですし。 この方法でサイズ取得するのはよく行われているようですが、記載が無い以上避けておいたほうがいいように思います。

sandayu999
質問者

補足

hofuhofuさん、返信ありがとうございます。 >それより改めて見直してみて気になったのは、 >GetAdaptersInfo(NULL,&aiSize); //サイズ取得 >ですね。 >確かに必要な容量がaiSizeに帰ってきていますが、 >この挙動自体はMSDNに記載されていないようです。 MSDNのサンプルを見てみたのですが、 pAdapterInfo = (IP_ADAPTER_INFO *) malloc( sizeof(IP_ADAPTER_INFO) ); ulOutBufLen = sizeof(IP_ADAPTER_INFO); if (GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) { GlobalFree (pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen); } この記述をみると、最初は、 IP_ADAPTER_INFO一つ分で確保しに行ってますが、 そのとき、if文で GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) をして、失敗だったらulOutBufLenを使用して 再度所得しなおしているので、MSDN上いちおう 問題ないのではないでしょうか?

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.4

>こちらはFREE関数を使ってメモリを最後に開放していないのですが、これはサンプルだから省略されたということでしょうか? >通常は、hohuhohuさんの書かれるとおり、最後にFREE を入れるべきですよね? 当たり前のことですが、free()を呼ぶのはその領域が不要になったとき。 MSDNのサンプル、関数にはなってないですよね。 取得したMACアドレス、printfで表示するだけでしたらすぐにfreeしてもいいですけど、他にも使うんでしたら解放しちゃまずいですよね。

sandayu999
質問者

お礼

taka_tetsuさん返信ありがとうございます。 >当たり前のことですが、free()を呼ぶのはその領域 >が不要になったとき。 >MSDNのサンプル、関数にはなってないですよね。 >取得したMACアドレス、printfで表示するだけでし >たらすぐにfreeしてもいいですけど、他にも使うん >でしたら解放しちゃまずいですよね。 なるほど、確かに関数になっていませんでした。 プログラムも理解することができました。 ありがとうございました。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>実際、自分のプログラム(雑誌に載っていたサンプル) >だとなぜエラーなのか原因がわからなかったのです。 書かれているコード、質問に書かれた部分で全部ですか? 使用してる変数の宣言からAPIの呼び出しまでの間を全部書いていただければどこがおかしいか確認できると思いますけど。 >ERROR_INVALID_PARAMETERについても英語で説明 >はありますが、、いまいち対処法をみいだすことが >できなくて。 ERROR_INVALID_PARAMETERは、「パラメータが間違ってます」ってだけなんで、使い方が違うとしか言いようが無いです。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1
sandayu999
質問者

お礼

taka_tetsuさん、返信ありがとうございます。 実は、自分も調べていて紹介していただいたURL にはいったのですが、 実際、自分のプログラム(雑誌に載っていたサンプル) だとなぜエラーなのか原因がわからなかったのです。 ERROR_INVALID_PARAMETERについても英語で説明 はありますが、、いまいち対処法をみいだすことが できなくて。 他にも、色々と調べてはみたのですが、 ERROR_INVALID_PARAMETER が出力されてしまっている状態です。

関連するQ&A

  • Borland C++ Compiler

    学校のC言語の授業で使用するので、Borland C++ Compilerをインストールしました。 今までに作ったプログラムや、教科書に載っていたサンプルプログラムをコンパイルして軽い勉強をしていたのですが、コンパイルの際にエラーが出るようになりました。 コマンドプロンプトでbcc32と打つと、パラメータのリストのようなものが出てくるので、-nなど適当にパラメータをつけて実行したら以下のようなエラーが出るようになりました。 Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland test.c: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: 外部シンボル '_main' が未解決(C:\BORLAND\BCC55\LIB\C0X32.OBJ が参照) objとtdsファイルは出力されるのですが、exeが出力されません。 どうやったらなおるか、教えてください。

  • OpenGLに関する質問

    BCCでOpenGLのWEBのサンプルプログラムをコンパイルしようと思うのですが、 Error: 'C:\BORLAND\BCC55\LIB\GLUT32.LIB' contains invalid OMF record, type 0x21 (possibly COFF) というエラーが出てコンパイルできません。 解決方法を教えてください。

  • コンパイルエラー

    本日からC++を勉強しはじめました。 使用しているコンパイラはBORLAND C++ COMPILER 5.5 です。 #include<iostream> int main(){ cout<<"hello"; return 0; } 上記をコンパイルすると下記のエラーが出ます。 いったいどこがいけないのでしょうか。 どなたか教えてくださいませ。 Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland 123.c: 致命的エラー F1003 C:\BORLAND\BCC55\include\stdcomp.h 5: error 指令: Must use C++ for STDCOMP.H *** 1 errors in Compile *** *** コンパイル終了 ***

  • C++言語でのライブラリファイルの作成と使用法

    よろしくお願いします。 C言語において、例えばMinGWのCコンパイラのLibディレクトリには、拡張子が「.a」のライブラリファイルがたくさん存在しています。これらは、arコマンドで ar crv libMine.a 1.o 2.o のように作成されるものだと認識しています。 一方、C++言語において、例えばBorlandのC++コンパイラのLibディレクトリには、拡張子が「.lib」というライブラリファイルがたくさん存在します。 これらのファイブラリファイルは、C言語のaファイルと同じ役割をする考えてよいのでしょうか? また、C++において自作のライブラリファイル(libファイル)を作成するにはどうすればよいのでしょうか? 次に、C++における自作ライブラリの使用法についてですが、Cではコンパイル時に gcc -o 1.exe 1.c libMine.a のようにして、自作のライブラリファイルを使うことができますが C++のコンパイルコマンド、例えばbcc32コマンドを使ってコンパイルする時に、 自分が作成したlibファイルを使うにはどのようにすればよいのでしょうか? 最後に、Borland C++コンパイラをインストールするときに、Binディレクトリにあるbcc.cfgファイルに -L"c:\Borland\Bcc55\lib" と記述したのですが、これは、 c:\Borland\Bcc55\libにあるlibファイルをコンパイル時に自動的に読み込むということなのでしょうか?

  • Borland C++ Compiler で winbase.h を使えないのですが・・・

    Borland C++ Compiler を使っているのですが,winbase.h 自体が使用できません。 次のようなプログラムでもコンパイルが通りません。 #include <winbase.h> int main(void){ return 0; } エラーは以下の通りです。 *** コンパイル開始 *** Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland ########.c: エラー E2139 C:\borland\bcc55\Include\winbase.h 227: 宣言に ; がない エラー E2238 C:\borland\bcc55\Include\winbase.h 228: 'ULONG_PTR' の宣言が複数見つかった エラー E2344 C:\borland\bcc55\Include\winbase.h 227: 一つ前の 'ULONG_PTR' の定義位置 (中略) エラー E2228 C:\borland\bcc55\Include\winbase.h 263: エラーあるいは警告が多すぎる *** 26 errors in Compile *** *** コンパイル終了 *** どうすればよいでしょうか? 何かちょっとした情報でもお願いします。

  • stdio.hをオープンできない…

    borlandのコンパイラーについての質問です(昔本付属のCDからインストールしたものです。verは5.5だと思われます。) ソースファイル include<stdio.h> void main(void){ printf("おめでとう!!\n"); } コンパイル c:\borland\bcc55\bin>bcc32 basic.c エラーメッセージはE2209 basic.c 1:インクルードファイルstdio.hをオープンできない、となります。このためprintfが使えないエラーメッセージも表示されます。過去の質問を色々と見させて頂きました。以前(昨年夏頃)には使えていた為、必要なファイルが消えている等の原因はなさそうです。メモ帳でbcc32も開いてみましたが-I"c:\borland\Bcc55\include"-L"c:\borland\Bcc55\libの表示があったので必要なファイルも開けているのではないかと勝手に解釈しています(bcc32.cfgフォルダなるものは存在しませんでしたが…)。いろいろと頑張ってみたのですがどうにもダメそうです。コンパイラが作動しないと課題が前に進まないため、大変困っています。是非皆様のお力をお貸し下さい。よろしくお願いします。

  • 【エラー】Cpadで初めてコンパイル

    Cpad for Borlandで以下のようなソースを書きコンパイルをしましたが、失敗し、行き詰っております。 当方、初プログラミングに挑戦しております。 <環境> OS:XP(HOME) コンパイラ:Borland C++ Compiler エディタ:Cpad for Borland <動作状況> ソース: #include <stdio.h> int main ( void ) { printf(mori); return 0; } エラー情報: 「コンパイルに失敗しました。 ファイル"ファイル"D:\source\test1.exe"は存在しません」 参考情報(参考にならないかもしれませんが…): ・コンパイラはDドライブにインストールしております。 ・コンパイラのパスはD:\borland\bcc55\Bin\bcc32.exeです。 以上、よろしくお願いいたします。

  • borland c++ 致命的エラー

    Borland c++のコンパイラーを使用しているのですが、以下のエラーが出て先に進めません、誰か教えてください 致命的エラー F1003 c:\borland\bcc 55\include\ stdcomp.h5 :error指令:Must use C++ for STDCMP.H

  • Borland C++ Compiler 5.5について

    (1)Borland C++ Compiler 5.5 (2)Turbo Debugger 5.5 (3)Bcc Dev(環境設定ツール) (4)C Pad for LSI C-86 をダウンロードしました。まず、アイコンが表示されません。 C\borland\bcc55\bin を全部見ましたが、コンパイラらしきものは入っていません。 Bcc Devを起動して、プログラムをうち、コンパイルしたと、実行とデッバグができません。 過去ログを見ましたが、参考になりません。どうすればいいのでしょうか?因みにBCC32とiLink32はあります。

  • bcc55のエラー(cox32.obj)

    コンパイルすると、いつも Fatal:ファイルCOX32.OBJが開けません と言うエラーが出てしまいます。 bcc55のbinフォルダーにbcc32.cfgというファイルを作り、中身に -I"c:\Borland\Bcc55\include" -L"c:\Borland\Bcc55\lib" ilink32.cfgには -L"c:\Borland\Bcc55\lib" となっています。 初歩的なことかもしれませんがよろしくお願いします。