关于OpenNETCF.Net.NetworkInformation命名空间的WirelessNetworkInterface类的Connect函数问题
2010-07-27 23:30 Aga.J 阅读(1803) 评论(2) 编辑 收藏 举报今天难得jack在线,而且回了我的问题,我赶紧抓住机会问了他好多好多和我现在头痛的事由关的问题(^ ^ 哈哈),这个问题就是和OpenNETCF.Net.NetworkInformation这个命名空间里的WirelessNetworkInterface类的Connect函数的参数String SSID 具体是传入什么有关,一开始我传入的是access point的名字,结果程序运行到这里就会死机,所以觉得不是传入名字,所以就问了jack,然后聊着聊着,聊了好多,他说看源码就知道怎么了,焕然大悟啊,我马上下载了个reflector(jack推荐的),然后把OpenNETCF.Net.NetworkInformation.dll的源码进行了详读,发现了下面的东西:
假设使用Connect函数的无参版的重载函数,如果不传入参数(默认为连接到preferred access point),则调用Conenct(""),然后该函数调用NDISUIO.SetOID(NDIS_OID.SSID, base.Name, Encoding.ASCII.GetBytes(SSID)),
所以这时候最后一个参数为长度为0的byte数组,然后SerOID函数里又使用这个数组初始化NDISQueryOid对象
NDISQueryOid queryOID = new NDISQueryOid(data.Length);
queryOID.Data = data;
/*
其中Data的set是这样的
set
{
this.ourSize = 8 + value.Length;
this.m_data = new byte[this.ourSize];
Buffer.BlockCopy(value, 0, this.m_data, 8, value.Length);
}
所以在长度为0的byte数组的情况下,m_data只有8字节长。这个时候还不知道保存了什么信息!!
*/
return SetOID(oid, adapterName, queryOID);
/*
SerOID具体实现是
fixed (byte* numRef = Encoding.Unicode.GetBytes(adapterName + '\0'))
{
queryOID.ptcDeviceName = numRef; //这里继续初始化queryOID的成员
/*
ptcDeviceName的set如下
set
{
Buffer.BlockCopy(BitConverter.GetBytes((uint) value), 0, this.m_data, 4, 4);
}
//所以得到结论是m_data的后四个字节保存的是adapterName的字节串
*/
queryOID.Oid = (uint) oid; //同上
/*
Oid的set如下:
set
{
Buffer.BlockCopy(BitConverter.GetBytes(value), 0, this.m_data, 0, 4);
}
//所以前四个字节保存的是oid,在这里是个常量,是SSID = 0xd010102
//具体不清楚是什么,或者和preferred access point有关,因为这个connect()无参的//重载函数是连接到preferred access point 用的
*/
try
{
ndisuio.Open(FileAccess.ReadWrite, FileShare.ReadWrite);
}
catch
{
throw new NetworkInformationException(Marshal.GetLastWin32Error());
}
try
{
ndisuio.DeviceIoControl(0x120814, queryOID.getBytes(), queryOID.getBytes());
//最后应该在这个函数进行操作(msdn上说这个函数causing the corresponding device to perform the specified operation),所以所有必要的信息都应该有,所以需要适配器名字,和access point的必要信息,所以如果connect函数是有参的那个重载函数的话,那么会先将传入的SSID串变为字节数组,复制给m_data的第8个字节开始的那部分字节子数组。
}
catch (Exception)
{
return false;
}
}
}
接下来入正题了,SSID是什么呢?
利用
public virtual string AssociatedAccessPoint
{
get
{
string str = "";
byte[] buffer = null;
try
{
buffer = NDISUIO.QueryOID(NDIS_OID.SSID, base.Name);
/*
这里的base.Name是适配器的名字,根据适配器和常量SSID = 0xd010102
QueryOID会ndisuio.DeviceIoControl的查询操作,但是这次传入的第一个参数是0x120804而前面使用这个函数时传入的参数是0x120814,使用这个函数的目的是为了得到适配器上的所有信息,然后保存在oid变量里,然后就把oid变量(包含了适配器名字,SSID = 0xd010102,和已连接的access point的信息)转换为buffer
*/
}
catch
{
return null;
}
int count = BitConverter.ToInt32(buffer, 0);
if (count > 0)
{
str = Encoding.ASCII.GetString(buffer, 4, count);
/*
这里将buffer从第4个字节开始转换为串,前四个字节保存的是什么就不知道了,估计也是适配器的名字
*/
}
return str; //返回串!
}
}
然后写一些测试代码
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(this.m_wzc.AssociatedAccessPoint);
}
我们得到的是目前适配器所连接的AP的名字!即上面的str = Encoding.ASCII.GetString(buffer, 4, count);返回的是当前连接的ap的名字
查看connect函数,里面的实现是NDISUIO.SetOID(NDIS_OID.SSID, base.Name, Encoding.ASCII.GetBytes(SSID),这样一来,我们就直接传进将要连接的ap的名字就行了。
至于为什么我的机子会死机,可能是因为山寨机的问题,也可能是因为这个类库适用性不是那么广吧,还要继续搞到能连接为止啊。上面只是记录了大概的过程,具体还有很多,我没写下来。
作者:Aga.J
出处:http://www.cnblogs.com/aga-j
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
个人学习笔记仅供本人记录知识所用,不属发表性文章。