• ベストアンサー
  • 暇なときにでも

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) となってしまいました。 どのような対処をしたら良いのかわからない状態です、どなたかアドバイスをよろしくお願いいたします。

共感・応援の気持ちを伝えよう!

  • 回答数6
  • 閲覧数2505
  • ありがとう数7

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

  • ベストアンサー
  • 回答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つの時にしか正常に動作しないような気がします。

共感・感謝の気持ちを伝えよう!

質問者からの補足

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)

  • 回答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が小さすぎること以外書かれていないので、この現象に依存したプログラムは避けるべきだと思います。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

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

  • 回答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で指定された値が必要な容量未満だったときですし。 この方法でサイズ取得するのはよく行われているようですが、記載が無い以上避けておいたほうがいいように思います。

共感・感謝の気持ちを伝えよう!

質問者からの補足

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上いちおう 問題ないのではないでしょうか?

  • 回答No.4

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

共感・感謝の気持ちを伝えよう!

質問者からのお礼

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

  • 回答No.2

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

共感・感謝の気持ちを伝えよう!

  • 回答No.1

共感・感謝の気持ちを伝えよう!

質問者からのお礼

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

関連するQ&A

  • iphlpapiのGetAdaptersInfoでNICのMacアドレスを取りたいのですが...

    こんにちは、 質問No.4996に関連して、VC++でiphlpapiのGetAdaptersInfoを使って、NICのMACアドレスを取得しようと考えています。WIN XP、WIN2000では、目的のアドレスが取得できるのですが、WIN98、WIN MEではNIC以外にPPP AdapterやAOL Adapterといった、ダイアルアップ用のアドレスも同時に取れてしまい、大変困っています。取得したものを見れば検討は付くのですがプログラム的により分ける方法が分かりません。確実にNICのMACアドレスだけを取得する方法はないでしょうか?NetBiosやiphlpapiの他の関数も検討しましたが、ネットワークが構築されていないPCから取得できるのはGetAdaptersInfoだけのようですので、出来ればこの関数を使って解決したいと考えています。どうか、よろしくお願いします。

  • DirectX SDKのインストールと設定

    使用しているコンパイラはborlandです。 DirectX SDKをインストールして、早速使ってみたのですが エラーがでてしまい、コンパイルが出来ません。 エラー内容は エラー E2451 test.c 26: 未定義のシンボルGetAdapterDisplayMode(関数WinMain) などの「未定義のシンボル」というエラーがずらりと出てしまいます。ソースは入門サイトから持ってきたものなのでソースには問題は無いと思います… どなたか教えてください。よろしくお願いします。

  • 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 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はあります。

  • 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です。 以上、よろしくお願いいたします。

  • フリーのコンパイラを探しています

    PC上で動作するフリー(若しくは無償で手に入れば期間限定版でも良いです)のCコンパイラ(C++もあれば尚可)を探しています。 目的は、あるサイトから取得した暗号化を行うソースをコンパイル&実行する為です。しかしながら、そのソースはかなり前にPC-98(NEC)で Turbo Cで確認したもので、int型が2バイトであることを前提にしています。試しにBorlandのコンパイラ(BCC32)でコンパイル&実行してもこちらの期待した結果は得られませんでした。(int型をshort型に変更しコンパイルしてもだめでした) 上記の条件にあてはまるものでLSC-Cがありますが、LSC-Cでコンパイルするとメモリ不足となり、コンパイルが異常終了してしまいます。 int型を2バイトとして扱うことのできるコンパイラをLSC-C以外にご存じでしたら教えていただけませんでしょうか。

  • OpenGLに関する質問

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

  • BCCでの日本語ファイル名の扱い

    こんにちは。 現在WindowsVistaで、Borland C++ Compiler 5.5(日本語版)を使い、プログラミングを行っています。 最近、bcc32.exeでソースファイルをコンパイルする際に、ソースファイルの名前に一部の日本語が含まれている場合は、コンパイルできないという事に気が付きました。 例えば、「161_ポインタの基礎.c」というソースファイルをコンパイル使用すると、以下の様にコンパイルエラーになります。 ------------------------------------------------------------ >bcc32 -c "161_ポインタの基礎.c" Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland 161_ポツンタの基礎.c: エラー F1009 161_ポツンタの基礎.c: 入力ファイル '161_ポツンタの基礎.c' をオープンできない *** 1 errors in Compile *** ------------------------------------------------------------ どうやら、「イ」という文字を、コンパイラが「ツ」と認識してしまっているようです。 こういった問題の解決策をWebで検索したのですが、見つける事ができませんでした。 ちなみに、僕の使っているBCCはすでに日本語版ですので、日本語化が必要というわけではなさそうです。 そこで解決策を御提供頂きたいと思っています。 何でもいいので、よろしくお願い致します。

  • コンパイルエラー

    本日から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 *** *** コンパイル終了 ***