【问题标题】:Pinvoke problem with the Windows helper APIWindows 帮助程序 API 的 Pinvoke 问题
【发布时间】:2009-07-09 20:08:46
【问题描述】:

这是我第一次认真尝试 P/invoke。这是我用来计算 Web 服务代码的控制台应用程序,它有望从 IP 地址或完全限定的系统名称返回 MAC 地址。代码编译。但是,当没有参数运行时,我得到一个未处理的异常-IndexOutOfRangeException。如果我使用 args 运行它,我会得到一个不同的未处理异常 AccessViolationException: Attempted to read or write protected memory。而且,我是自学成才的......如果我做了一些愚蠢的事情,请善待。这是我的代码:

using System;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;

namespace GetMac
{
    class Program
    {
        const int NET_STRING_IPV4_ADDRESS = 1;   // 192.168.100.10
        const int NET_STRING_IPV4_SERVICE = 2;   // 192.168.100.10:80
        const int NET_STRING_IPV4_NETWORK = 4;   // 192.168.100/24
        const int NET_STRING_IPV6_ADDRESS = 8;   // 21DA:00D3:0000:2F3B:02AA:00FF:FE28:9C5A%2
        const int NET_STRING_IPV6_ADDRESS_NO_SCOPE = 8;  // 21DA:00D3:0000:2F3B:02AA:00FF:FE28:9C5A
        const int NET_STRING_IPV6_SERVICE = 32;   // [21DA:00D3:0000:2F3B:02AA:00FF:FE28:9C5A%2]:8080
        const int NET_STRING_IPV6_SERVICE_NO_SCOPE = 64;  // 21DA:00D3:0000:2F3B:02AA:00FF:FE28:9C5A:8080
        const int NET_STRING_IPV6_NETWORK = 128;   // 21DA:D3::/48
        const int NET_STRING_NAMED_ADDRESS = 256;  // www.microsoft.com
        const int NET_STRING_NAMED_SERVICE = 512;  // www.microsoft.com:80

        internal static class NativeMethods
        {
            [DllImport("IpHlpApi.dll", CharSet = CharSet.Unicode)]
            //public static extern uint ParseNetworkString(ref string networkString, int types, out NetAddressInfo addressInfo, out ushort portNumber, out byte prefixLength);
            public static extern uint ParseNetworkString(string networkString, int types);
        }

        public static string GetMacAddress(IPAddress ipAddress)
        {
            string strMacAddress = string.Empty;

            try
            {
                char delimChar = '=';
                string strTempMacAddress = string.Empty;
                ProcessStartInfo objProcessStartInfo = new ProcessStartInfo();
                Process objProcess = new Process();
                objProcessStartInfo.FileName = "nbtstat";
                objProcessStartInfo.RedirectStandardInput = false;
                objProcessStartInfo.RedirectStandardOutput = true;
                objProcessStartInfo.Arguments = "-A " + ipAddress;
                objProcessStartInfo.UseShellExecute = false;
                objProcess = Process.Start(objProcessStartInfo);

                int Counter = -1;
                while (Counter <= -1)
                {
                    Counter = strTempMacAddress.Trim().ToLower().IndexOf("mac address", 0);
                    if (Counter > -1)
                    {
                        break;
                    }
                    strTempMacAddress = objProcess.StandardOutput.ReadLine();
                }
                objProcess.WaitForExit();
                string[] words = strTempMacAddress.Split(delimChar);
                strTempMacAddress = words[1];
                strMacAddress = strTempMacAddress.Trim();
                strMacAddress = strMacAddress.Replace('-', ':');
            }
            catch (Exception Ex)
            {
                Console.WriteLine(Ex.ToString());
                Console.ReadLine();
            }
            return strMacAddress;
        }

        static void Main(string[] args)
        {
            string macAddress = null;
            IPAddress ipAddress = null;
            string strHostOrIp;

            if (args[0] == null)
            {
                Console.WriteLine("Please enter an IP address or fully qualified host name");
                return;
            }
            else
            {
                strHostOrIp = args[0];
            }
            if (NativeMethods.ParseNetworkString(strHostOrIp, NET_STRING_IPV4_ADDRESS) == 0) //true if it's an IP address
            {
                IPAddress address = IPAddress.Parse(strHostOrIp);
                ipAddress = address;
            }
            else if (NativeMethods.ParseNetworkString(strHostOrIp, NET_STRING_NAMED_SERVICE) == 0) //true if it's a fully qualified host name
            {
                IPHostEntry hostEntry = null;
                try
                {
                    hostEntry = Dns.GetHostEntry(strHostOrIp);
                }
                catch
                {
                    return;
                }
                if (hostEntry.AddressList.Length == 0)
                {
                    return;
                }
                foreach (IPAddress ip in hostEntry.AddressList)
                {
                    if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) // true if we have IPv4
                    {
                        ipAddress = ip;
                        break;
                    }
                }
            }
            else
            {
                ipAddress = null;
            }
            macAddress = GetMacAddress(ipAddress);
            Console.WriteLine(macAddress);
        }
    }
}
// DWORD WINAPI ParseNetworkString( -in const WCHAR *NetworkString, 
//                                  -in DWORD Types, 
//                                  -out_opt  PNET_ADDRESS_INFO AddressInfo, 
//                                  -out_opt  USHORT *PortNumber, 
//                                  -out_opt  BYTE *PrefixLength);

// ParseNetworkString function parses the input network string and checks whether it is a legal 
// representation of the specified IP network string type. If the string matches a type and its 
// specification, the function can optionally return the parsed result

// Return Value
// If the function succeeds, the return value is ERROR_SUCCESS. // I think this means it returns 0.
// If the function fails, the return value is one of the following error codes.
//  ERROR_INSUFFICIENT_BUFFER - The buffer passed to the function is too small. This error is returned if the buffer pointed to by the AddressInfo parameter is too small to hold the parsed network address.
//  ERROR_INVALID_PARAMETER - An invalid parameter was passed to the function. This error is returned if a NULL pointer is passed in the NetworkString parameter

// http://msdn.microsoft.com/en-us/library/bb408412(VS.85).aspx

提前感谢。

【问题讨论】:

    标签: c# networking interop


    【解决方案1】:

    这是一个“更”正确的 DllImport:

    [DllImport("iphlpapi.dll", CharSet = CharSet.Unicode)]
    public static extern uint ParseNetworkString(string networkString, uint types, IntPtr addressInfo, IntPtr portNumber, IntPtr prefixLength);
    

    示例用法:

    Console.WriteLine(ParseNetworkString("192.168.100.10:20", NET_STRING_IPV4_SERVICE, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero));
    

    【讨论】:

      【解决方案2】:

      ParseNetworkString 的三个“可选”参数不是可选的,因为您可以省略它们。您必须提供它们,但您可以传递 null(或零)表示您不希望返回该特定值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-28
        相关资源
        最近更新 更多