梦幻情缘 发表于 2006-3-10 12:19

获得局域网中计算机的列表(包括计算机名,IP和MAC)的方法

有的时候需要根据MAC来限定登录的计算机,为此查找了不少资料(有来自博客堂和CSDN),下面是获得远程计算机的MAC和局域网中计算机列表的方法。<BR>
<P>using System; </P>
<P>using System.Collections; </P>
<P>using System.Diagnostics; </P>
<P>using System.Management; </P>
<P>using System.Net; </P>
<P>using System.DirectoryServices; </P>
<P>using System.Runtime.InteropServices; </P>
<P>using System.Text.RegularExpressions; </P>
<P>获得本机的MAC地址 </P>
<P>        public static string GetLocalMac() </P>
<P>        { </P>
<P>            string strMac = string.Empty; </P>
<P>            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); </P>
<P>            ManagementObjectCollection moc = mc.GetInstances(); </P>
<P>            foreach(ManagementObject mo in moc) </P>
<P>            { </P>
<P>                if ((bool)mo["IPEnabled"] == true) </P>
<P>                    strMac += mo["MacAddress"].ToString() ; </P>
<P>  </P>
<P>            } </P>
<P>            return strMac.ToUpper(); </P>
<P>        } </P>
<P>获得远程计算机的MAC地址 </P>
<P>方法一:使用API,利用ARP协议,只能获得同网段计算机的MAC </P>
<P>        [DllImport("Iphlpapi.dll")] </P>
<P>        private static extern int SendARP(Int32 dest,Int32 host,ref Int64 mac,ref Int32 length); </P>
<P>        [DllImport("Ws2_32.dll")] </P>
<P>        private static extern Int32 inet_addr(string ip); </P>
<P>        public static string GetRemoteMac(string clientIP) </P>
<P>        { </P>
<P>            string ip = clientIP; </P>
<P>            if ( ip == "127.0.0.1") </P>
<P>                ip = GetLocalIP()[0]; </P>
<P>            Int32 ldest=inet_addr(ip); </P>
<P>            Int64 macinfo=new Int64(); </P>
<P>            Int32 len=6; </P>
<P>            try </P>
<P>            { </P>
<P>                SendARP(ldest,0,ref macinfo,ref len); </P>
<P>            } </P>
<P>            catch </P>
<P>            { </P>
<P>                return ""; </P>
<P>            } </P>
<P>            string originalMACAddress = Convert.ToString(macinfo,16); </P>
<P>            if (originalMACAddress.Length&lt;12) </P>
<P>            { </P>
<P>                originalMACAddress = originalMACAddress.PadLeft(12,'0'); </P>
<P>            } </P>
<P>            string macAddress; </P>
<P>            if(originalMACAddress!="0000" &amp;&amp; originalMACAddress.Length==12) </P>
<P>            { </P>
<P>                string mac1,mac2,mac3,mac4,mac5,mac6; </P>
<P>                mac1=originalMACAddress.Substring(10,2); </P>
<P>                mac2=originalMACAddress.Substring(8,2); </P>
<P>                mac3=originalMACAddress.Substring(6,2); </P>
<P>                mac4=originalMACAddress.Substring(4,2); </P>
<P>                mac5=originalMACAddress.Substring(2,2); </P>
<P>                mac6=originalMACAddress.Substring(0,2); </P>
<P>                macAddress=mac1+"-"+mac2+"-"+mac3+"-"+mac4+"-"+mac5+"-"+mac6; </P>
<P>            } </P>
<P>            else </P>
<P>            { </P>
<P>                macAddress=""; </P>
<P>            } </P>
<P>            return macAddress.ToUpper(); </P>
<P>        } </P>
<P><BR>方法二:使用windows的命令nbtstat </P>
<P><BR>        public static string GetRemoteMacByNetBIOS(string clientIP) </P>
<P>        { </P>
<P>            string ip = clientIP; </P>
<P>            if ( ip == "127.0.0.1") </P>
<P>                ip = GetLocalIP()[0]; </P>
<P>            string dirResults=""; </P>
<P>            ProcessStartInfo psi  = new ProcessStartInfo(); </P>
<P>            Process proc = new Process(); </P>
<P>            psi.FileName = "nbtstat.exe"; </P>
<P>            //psi.RedirectStandardInput = false; </P>
<P>            psi.RedirectStandardOutput = true;psi.RedirectStandardError=true; </P>
<P>            psi.Arguments = "-A " + ip; </P>
<P>            psi.UseShellExecute = false; </P>
<P>            proc = Process.Start(psi); </P>
<P>            dirResults = proc.StandardOutput.ReadToEnd(); </P>
<P>            string error = proc.StandardError.ReadToEnd(); </P>
<P>            proc.WaitForExit(); </P>
<P>            dirResults=dirResults.Replace("\r","").Replace("\n","").Replace("\t",""); </P>
<P>  </P>
<P>            Regex reg=new Regex("Mac[ ]{0,}Address[ ]{0,}=[ ]{0,}(?((.)*?))__MAC",RegexOptions.IgnoreCase|RegexOptions.Compiled); </P>
<P>            Match mc=reg.Match(dirResults+"__MAC"); </P>
<P>  </P>
<P>            if(mc.Success) </P>
<P>            { </P>
<P>                return mc.Groups["key"].Value.ToUpper(); </P>
<P>            } </P>
<P>            else </P>
<P>            {                    </P>
<P>               return ""; </P>
<P>            } </P>
<P>        } </P>
<P>使用此方法需要足够的操作系统的权限。在Web中,可以将ASP.net用户加入管理员组。 </P>
<P>对于上面两个地方都用到的GetLocalIP是一个获取本机IP的方法: </P>
<P>        public static string[] GetLocalIP() </P>
<P>        { </P>
<P>            string hostName = Dns.GetHostName(); </P>
<P>            IPHostEntry ipEntry=Dns.GetHostByName(hostName); </P>
<P>            IPAddress[] arr=ipEntry.AddressList; </P>
<P>            string[] result = new string[arr.Length]; </P>
<P>            for(int i=0;i </P>
<P>            { </P>
<P>                result[i] = arr[i].ToString();   </P>
<P>            } </P>
<P>            return result; </P>
<P>        } </P>
<P><BR>获得局域网内计算机的列表 </P>
<P>方法一:使用逐个IP地址扫描的方式</P>
<P>利用多线程来对每个IP逐个扫描。</P>
<P>ComputerAddressInfo cai = new ComputerAddressInfo("192.168.1",42,53); </P>
<P>Thread thScan = new Thread(new ThreadStart(cai.ScanComputers)); </P>
<P>thScan.Start(); </P>
<P>// </P>
<P>    public class ComputerAddressInfo </P>
<P>    { </P>
<P>        private int startIP = 0; </P>
<P>        private int endIP = 0; </P>
<P>        private string ipPrefix = ""; </P>
<P>        private ArrayList computerList = null; </P>
<P>   </P>
<P>        public ComputerAddressInfo(string ipPrefix,int startIP,int endIP) </P>
<P>        { </P>
<P>            this.startIP = startIP; </P>
<P>            this.endIP = endIP; </P>
<P>            this.ipPrefix = ipPrefix; </P>
<P>            computerList = new ArrayList(); </P>
<P>        } </P>


<P>  <BR>        public void ScanComputers() </P>
<P>        { </P>
<P>            for(int i=startIP;i&lt;=endIP;i++) </P>
<P>            { </P>
<P>                string scanIP = ipPrefix +"."+i.ToString(); </P>
<P>                IPAddress myScanIP = IPAddress.Parse(scanIP); </P>
<P>                IPHostEntry myScanHost = null; </P>
<P>                string[] arr = new string[2]; </P>
<P>                try </P>
<P>                { </P>
<P>                    myScanHost = Dns.GetHostByAddress(myScanIP); </P>
<P>                } </P>
<P>                catch </P>
<P>                { </P>
<P>                    continue; </P>
<P>                } </P>
<P>                if (myScanHost != null) </P>
<P>                { </P>
<P>                    arr[0] = myScanHost.HostName; </P>
<P>                    arr[1] = scanIP; </P>
<P>                    computerList.Add(arr); </P>
<P>                } </P>
<P>            } </P>
<P>        } </P>
<P>    } </P>
<P><BR>此方法速度比较慢。</P>
<P>方法二:使用Active Directory </P>
<P>        public static ArrayList GetComputerList()  </P>
<P>        {  </P>
<P>            ArrayList list = new ArrayList(); </P>
<P>            //or  use  "WinNT://your_domain_name"  </P>
<P>            DirectoryEntry  root  =  new  DirectoryEntry("WinNT:"); </P>
<P>            DirectoryEntries  domains  =  root.Children;  </P>
<P>            domains.SchemaFilter.Add("domain");  </P>
<P>            foreach  (DirectoryEntry  domain  in  domains)  </P>
<P>            {    </P>
<P>                DirectoryEntries  computers  =  domain.Children;  </P>
<P>                computers.SchemaFilter.Add("computer");  </P>
<P>                foreach  (DirectoryEntry  computer  in  computers)  </P>
<P>                {  </P>
<P>                    object[] arr = new string[3]; </P>
<P>                    IPHostEntry  iphe = null; </P>
<P>                    try </P>
<P>                    { </P>
<P>                        iphe  =  Dns.GetHostByName(computer.Name); </P>
<P>                    } </P>
<P>                    catch </P>
<P>                    { </P>
<P>                        continue; </P>
<P>                    } </P>
<P>                    arr[0] = domain.Name; </P>
<P>                    arr[1] = computer.Name; </P>
<P>                    if ( iphe != null &amp;&amp; iphe.AddressList.Length &gt;0 ) </P>
<P>                    { </P>
<P>                        for ( int i=0;i </P>
<P>                            arr[2] += iphe.AddressList[i].ToString()+","; </P>
<P>                        arr[2] = arr[2].ToString().Remove(arr[2].ToString().Length-1,1); </P>
<P>                    } </P>
<P>                    else </P>
<P>                        arr[2] = ""; </P>
<P>                    list.Add(arr); </P>
<P>                }  </P>
<P>            }  </P>
<P>            return list; </P>
<P>        }  </P>
<P><BR>此方法速度也比较慢。</P>
<P>后记 </P>
<P>上面两个获得局域网内的计算机列表的方法都很费时,目前还没有找到更好的办法。</P>

dazhi_ 发表于 2006-3-14 22:16

<P>没有人学习网络方面编程的吗[em01]</P>

nieyouqing 发表于 2006-3-19 20:35

<P>楼主我想问一下这个程中出现这个问题应该怎么解决?<BR><BR><BR> 类型或命名空间名称“Management”在类或命名空间“System”中不存在(是否缺少程序集引用?)<BR></P>

kevinhou 发表于 2006-10-17 13:34

<P>me too !<BR> <BR>类型或命名空间名称“Management”在类或命名空间“System”中不存在(是否缺少程序集引用?)<BR></P>

CrazyWeed0907 发表于 2006-10-17 13:49

<P>using System.Management</P>

IT浪子 发表于 2006-12-12 20:41

楼上的Management好像点不出来吧,可以添加应用来添加这个命名空间的,

yz870735 发表于 2008-6-25 11:57

有没有VB版本的 `我C#不懂  ``

雪雨星风 发表于 2008-6-25 12:23

[em14]

gotowest 发表于 2008-8-4 16:05

顶版主一下,我正缺这样的资料。很不错。

页: [1]

编程论坛