说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

用C#调用packet.dll里的函数出错,请高手帮忙调一下!

编辑:说三道四文库 发布时间:2018-05-22 06:14
HTML文档下载 WORD文档下载 PDF文档下载
packet.dll里有个函数PacketGetAdapterNames,带两个参数sStr和bufferSize,一个是存放网卡信息的缓冲区,另一个是缓冲区大小。我写一段代码运行之后函数已经返回true了,bufferSize也被改了,但是sStr没变。代码贴在下面了,很着急,请哪位高手帮忙调一下,谢谢!




    public partial class Form1 : Form
    {
        [DllImport("packet.dll",EntryPoint="PacketGetAdapterNames",CharSet=CharSet.Ansi)]
        public static extern bool PacketGetAdapterNames([MarshalAs(UnmanagedType.LPStr)]string sStr, ref int BufferSize);
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            bool b = false;
            int length = 40;
            string an = new string('0',length);
            b = PacketGetAdapterNames(an, ref length);
            NetworkInterface[] ni = NetworkInterface.GetAllNetworkInterfaces();
            label1.Text = an;
        }
    }

你PacketGetAdapterNames函数的原型是什么? 

public static extern bool PacketGetAdapterNames([MarshalAs(UnmanagedType.LPStr)]string sStr, ref int BufferSize);

你这样的调用方式sStr肯定是不会改变的。、
你的C函数原型中该位置要么是char** sStr,要么是char*&.这样才能改变传进来的值。
C#中相应处也应该是类似ref string..
感谢!不过函数的原型是LPStr string,昨天晚上试了一晚上,忘了试的是ref string还是ref char[]了,好像都不行,中午回宿舍才能再试,呵呵!
什么叫 LPStr   string,我问你的C++函数的原型是什么?
以前只用过C++开发过WinPcap的东东

第一个参数可以用这个试试:


//声明:
[DllImport("packet.dll",EntryPoint="PacketGetAdapterNames",CharSet=CharSet.Ansi)]
public static extern bool PacketGetAdapterNames(StringBuilder adapterName, ref int BufferSize);

//使用:

while (1)
{
    StringBuilder sb = new StringBuilder(260);
    int bufLen = 260;

    if (PacketGetAdapterNames(sb, ref bufLen))
    {
        // 做你想做的事,比如把得到的网卡名放到一个List里
     }
    else
    {
        break;
    }
}
其实CharSet=CharSet.Ansi 这个不该设置,我拷贝楼主的代码时没注意
不设置应该默认Auto

还有可能用户机器会有不止一个网卡(比如用VM虚拟机),所以需要在一个循环里读取,直到枚举完为止
楼上的大哥,按你的方法还是没返回正确的结果,sb里面是空的,无奈啊。。。。。。
麻烦大家说说自己用的WinPcap都是哪一版的啊?我又试了4.01、02、03这三个版本的,都不行
为了解决你问题,你又不肯给出函数的原型,自己搜了一下
PacketGetAdapterNames ,。你的问题出在,string sStr 这个是WCHAR * 类型,所以是宽字符的,所以

([MarshalAs(UnmanagedType.LPWStr)]string sStr
楼上的大哥实在是不好意思,我在Packet32.h里面看到的sStr类型为PTSTR,试着用你的方法改我的程序,同样得不到网卡名字列表。我想知道这个函数返回的网卡名字到底是注册表中的那个键值?知道的话就可以用C#里面自带的函数了,我的目的很简单,就是要找到网卡的名字然后打开它用它给交换机发送数据包。
在WINDOWS头文件中定义如下,、
typedef LPWSTR PTSTR, LPTSTR;
typedef __nullterminated NWPSTR, *LPWSTR, *PWSTR;

所以PTSTR 就是WCHAR *。

奇怪。你的字符集CharSet=CharSet.Unicode,数据类型用StringBuilder也不行。。?
都试过了啊,就是不行,运行之后b的值能改成true,length能变成242,就是an不变,还有什么办法能得到网卡名字吗?
有个问题:
你的机器上要先安装同版本的WinPCAP驱动才行
否则光用dll是得不到的
还有没有发现楼主有初始化pcap lib啊?!
你看看.h头文件,应该先调用初始化库的函数  然后再调用其他功能函数
这个我记得不是很清了,也许你用的这个函数无需初始化pcap库
up
回palmax大哥,我装winpcap了,小弟才疏学浅,还不知道C#里面初始化库的函数怎么写,pcap lib库具体在什么地方
转化成byte数组再传过去吧

            //声明:


                        [DllImport("packet.dll",EntryPoint="PacketGetAdapterNames",CharSet=CharSet.Auto)]
public static extern bool PacketGetAdapterNames(ref byte[] adapterName, ref int BufferSize);

//使用:

while (1)
{

    if (PacketGetAdapterNames(sb, ref bufLen))
    {
      //把byte数组转化为你要的字符串
        // 做其他事
     }
    else
    {
        break;
    }
}
楼主:

昨天上网查了下,你的这个PacketGetAdapterNames函数是不用其他初始化的,它是第一个要调用的函数,它是读注册表的,返回的sStr是网卡名的连续字符串,中间用一定的字符来分隔的,我现在手里没PCAP的环境,要不你再试试:

//声明:
[DllImport("packet.dll",EntryPoint="PacketGetAdapterNames",CharSet=CharSet.Auto)]
public static extern bool PacketGetAdapterNames([MarshalAs(UnmanagedType.LPStr)]StringBuilder adapterName, ref int BufferSize);

//使用:
StringBuilder sb = new StringBuilder(4096);
int bufLen = 4096;

if (PacketGetAdapterNames(sb, ref bufLen))
{
    // 做你想做的事,比如把得到的网卡名放到一个List里
}
搞定,谢谢!
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘