我需要获取Windows中网络接口的索引。
有NetworkInterface.getIndex()方法可以执行此操作,但是仅从Java 7开始才可用。
老板的要求是该应用程序需要在Java 6中运行。
经过一些搜索,我发现JNA lib可以调用Win API函数。
函数本身是GetIfTable(http://msdn.microsoft.com/en-us/library/windows/desktop/aa365943(v=vs.85).aspx)
但是,我无法使用JNA成功调用此函数。
GetIfTable的返回值始终为122,这意味着ERROR_INSUFFICIENT_BUFFER。即使我继续添加缓冲区,它仍然表示缓冲区不足,直到提供的值达到一定数量时,才会显示“无效的内存访问”错误。
这是我已经做过的:
public interface IpHlpAPI extends StdCallLibrary {
IpHlpAPI INSTANCE = (IpHlpAPI) Native.loadLibrary("IpHlpAPI", IpHlpAPI.class);
public static class MIB_IFTABLE extends Structure {
public int dwNumEntries;
public MIB_IFROW table[] = new IpHlpAPI.MIB_IFROW[1];
public MIB_IFTABLE() {}
public MIB_IFTABLE(int size) {
this.allocateMemory(size);
}
@Override
protected List getFieldOrder() {
return Arrays.asList(new String[]{"dwNumEntries", "table"});
}
}
public static class MIB_IFROW extends Structure {
public char wszName[] = new char[256];
public int dwIndex;
public int dwType;
public int dwMtu;
public int dwSpeed;
public int dwPhysAddrLen;
public byte bPhysAddr[] = new byte[8];
public int dwAdminStatus;
public int dwOperStatus;
public int dwLastChange;
public int dwInOctets;
public int dwInUcastPkts;
public int dwInNUcastPkts;
public int dwInDiscards;
public int dwInErrors;
public int dwInUnknownProtos;
public int dwOutOctets;
public int dwOutUcastPkts;
public int dwOutNUcastPkts;
public int dwOutDiscards;
public int dwOutErrors;
public int dwOutQLen;
public int dwDescrLen;
public byte bDescr[] = new byte[256];
@Override
protected List getFieldOrder() {
return Arrays.asList(new String[]{"wszName", "dwIndex", "dwType", "dwMtu",
"dwSpeed", "dwPhysAddrLen", "bPhysAddr", "dwAdminStatus", "dwOperStatus",
"dwLastChange", "dwInOctets", "dwInUcastPkts", "dwInNUcastPkts", "dwInDiscards",
"dwInErrors", "dwInUnknownProtos", "dwOutOctets", "dwOutUcastPkts",
"dwOutNUcastPkts", "dwOutDiscards", "dwOutErrors", "dwOutQLen", "dwDescrLen", "bDescr"});
}
}
int GetIfTable(MIB_IFTABLE pIfTable, IntByReference pdwSize, boolean bOrder);
}
public static void main(String[] args) {
IpHlpAPI ipHlpApi = IpHlpAPI.INSTANCE;
IpHlpAPI.MIB_IFTABLE ifTable = new IpHlpAPI.MIB_IFTABLE();
IntByReference psize = new IntByReference(ifTable.size());
int status = ipHlpApi.GetIfTable(ifTable, psize, false);
if (status == 122) {
// Calculate the required number of elements in the MIB_IFROW array
ifTable = new IpHlpAPI.MIB_IFTABLE((psize.getValue() - 4) / ifTable.table[0].size());
psize.setValue(ifTable.size());
status = ipHlpApi.GetIfTable(ifTable, psize, false);
System.out.println(status);
}
System.exit(0);
}
任何想法为什么会这样?
最佳答案
您的输入结构不够大。您需要根据table
参数中返回的值来重新分配pdwSize
字段,使其足够大。
向MIB_IFTABLE
添加一个指示table
数组大小的构造函数,并相应地对其进行初始化。这将自动为您提供更大的缓冲。
MIB_IFTABLE ifTable = new MIB_IFTABLE();
IntByReference psize = new IntByReference(ifTable.size());
int status = ipHlpApi.GetIfTable(ifTable, psize, false);
if (status == 122) {
// Calculate the required number of elements in the MIB_IFROW array
ifTable = new MIB_IFTABLE((psize.getValue() - 4) / ifTable.table[0].size());
psize.setValue(ifTable.size());
status = ipHlpApi.GetIfTable(ifTable, psize, false);
// If status is still 122, then there's an issue with the MIB_IFROW definition
// ...
}
编辑
更改您的构造函数:
public MIB_IFTABLE(int nentries) {
this.dwNumEntries = nentries;
this.table = (MIB_IFROW[])new MIB_IFROW().toArray(nentries);
}
您可能应该将其他ctor初始化为
dwNumEntries
的默认值。因为它是您将传入的默认值零,这将确保您在第一次调用时得到的返回值为122。我假设dwNumEntries
是指数组的大小。