windows 在 C# 中查询 DHCP 服务器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2224877/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Querying a DHCP server in C#
提问by Kazoom
I need to get the mapping of MAC to IP stored on DHCP server, either through a program running on the server itself or preferably through a program running on one of the DHCP clients.
我需要通过在服务器本身上运行的程序或最好通过在其中一个 DHCP 客户端上运行的程序来获取存储在 DHCP 服务器上的 MAC 到 IP 的映射。
I understand netsh utilitycan be used to get the dump however i have not had much success with that.
我知道netsh 实用程序可用于获取转储,但是我并没有取得太大的成功。
Any working examples or hint on that?
任何工作示例或提示?
I have admin rights on DHCP server
我有 DHCP 服务器的管理员权限
Edit
编辑
I dont want to use arp cache as that would require me to either broadcast ping (which is not allowed on windows) or ping the all possible ip address of subnet( which takes lot of time).
我不想使用 arp 缓存,因为这需要我广播 ping(Windows 上不允许)或 ping 子网的所有可能的 ip 地址(这需要很多时间)。
I am sure that DHCP server stores the mapping of MAC to IP, how can i use that information, to map MAC to IP address?
我确定 DHCP 服务器存储了 MAC 到 IP 的映射,我如何使用该信息将 MAC 映射到 IP 地址?
回答by bzlm
You can use the DHCP Objects componentfrom the Windows 2000 Resource Kitfor this. Even though the component is hard to find, is made for Windows 2000, goes out of life support in July 2010 according to Microsoft and has very little documentation, it does work.
您可以使用DHCP组件对象从Windows 2000的资源工具包这一点。尽管该组件很难找到,是为 Windows 2000 制造的,根据 Microsoft 的说法于 2010 年 7 月停止支持并且文档很少,但它确实有效。
- Download the Resource Kit Tool named DHCP Objectsfrom for example hereif you can't find it at Microsoft. This will give you an .exe file that in turn will install the DHCP Objects component.
- Register the
DHCPOBJS.DLL
file withregsvr32
orcreate a COM+ Application for it. Which is applicable depends on how the COM component is going to be used on your system. - Use the Type Library Importer
tlbimp.exe
to create a managed wrapper aroundDHCPOBJS.DLL
now that it's registered by the system. - In Visual Studio, add a reference to the managed wrapper. Its default generated name is
DhcpObjects.dll
.
- 如果您在 Microsoft 上找不到名为DHCP 对象的资源工具包工具,请从这里下载。这将为您提供一个 .exe 文件,该文件将安装 DHCP 对象组件。
- 向其注册
DHCPOBJS.DLL
文件regsvr32
或为其创建 COM+ 应用程序。哪个适用取决于 COM 组件将如何在您的系统上使用。 - 使用类型库导入
tlbimp.exe
器创建一个托管包装器,DHCPOBJS.DLL
因为它已被系统注册。 - 在 Visual Studio 中,添加对托管包装器的引用。它的默认生成名称是
DhcpObjects.dll
.
Now you can write code like this against the component:
现在您可以针对组件编写这样的代码:
using DhcpObjects;
class Program {
static void Main(string[] args) {
var manager = new Manager();
var server = dhcpmgr.Servers.Connect("1.2.3.4");
// query server here
}
}
The installer also provides a Windows Help File which contains further documentation on how to query and manipulate a DHCP server. The section "The Object Model" is quite helpful.
安装程序还提供了一个 Windows 帮助文件,其中包含有关如何查询和操作 DHCP 服务器的进一步文档。“对象模型”一节非常有帮助。
回答by AZ_
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Net;
namespace dhcp
{
// c# class for processed clients
public class dhcpClient
{
public string hostname { get; set; }
public string ip { get; set; }
public string mac { get; set; }
}
// structs for use with call to unmanaged code
[StructLayout(LayoutKind.Sequential)]
public struct DHCP_CLIENT_INFO_ARRAY
{
public uint NumElements;
public IntPtr Clients;
}
[StructLayout(LayoutKind.Sequential)]
public struct DHCP_CLIENT_UID
{
public uint DataLength;
public IntPtr Data;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DHCP_CLIENT_INFO
{
public uint ip;
public uint subnet;
public DHCP_CLIENT_UID mac;
[MarshalAs(UnmanagedType.LPWStr)]
public string ClientName;
[MarshalAs(UnmanagedType.LPWStr)]
public string ClientComment;
}
// main
class Program
{
static void Main()
{
try
{
// get settings
String server, subnet;
Console.Write("Enter server : ");
server = Console.ReadLine();
Console.Write("Enter subnet : ");
subnet = Console.ReadLine();
// gather clients
ArrayList clients = findDhcpClients(server, subnet);
// output results
Console.WriteLine();
foreach (dhcpClient d in clients)
Console.WriteLine(String.Format("{0,-35} {1,-15} {2,-15}", d.hostname, d.ip, d.mac));
Console.WriteLine('\n' + clients.Count.ToString() + " lease(s) in total");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.ReadLine();
}
static ArrayList findDhcpClients(string server, string subnet)
{
// set up container for processed clients
ArrayList foundClients = new ArrayList();
// make call to unmanaged code
uint parsedMask = StringIPAddressToUInt32(subnet);
uint resumeHandle = 0;
uint numClientsRead = 0;
uint totalClients = 0;
IntPtr info_array_ptr;
uint response = DhcpEnumSubnetClients(
server,
parsedMask,
ref resumeHandle,
65536,
out info_array_ptr,
ref numClientsRead,
ref totalClients
);
// set up client array casted to a DHCP_CLIENT_INFO_ARRAY
// using the pointer from the response object above
DHCP_CLIENT_INFO_ARRAY rawClients =
(DHCP_CLIENT_INFO_ARRAY)Marshal.PtrToStructure(info_array_ptr, typeof(DHCP_CLIENT_INFO_ARRAY));
// loop through the clients structure inside rawClients
// adding to the dchpClient collection
IntPtr current = rawClients.Clients;
for (int i = 0; i < (int)rawClients.NumElements; i++)
{
// 1. Create machine object using the struct
DHCP_CLIENT_INFO rawMachine =
(DHCP_CLIENT_INFO)Marshal.PtrToStructure(Marshal.ReadIntPtr(current), typeof(DHCP_CLIENT_INFO));
// 2. create new C# dhcpClient object and add to the
// collection (for hassle-free use elsewhere!!)
dhcpClient thisClient = new dhcpClient();
thisClient.ip = UInt32IPAddressToString(rawMachine.ip);
thisClient.hostname = rawMachine.ClientName;
thisClient.mac = String.Format("{0:x2}{1:x2}.{2:x2}{3:x2}.{4:x2}{5:x2}",
Marshal.ReadByte(rawMachine.mac.Data),
Marshal.ReadByte(rawMachine.mac.Data, 1),
Marshal.ReadByte(rawMachine.mac.Data, 2),
Marshal.ReadByte(rawMachine.mac.Data, 3),
Marshal.ReadByte(rawMachine.mac.Data, 4),
Marshal.ReadByte(rawMachine.mac.Data, 5));
foundClients.Add(thisClient);
// 3. move pointer to next machine
current = (IntPtr)((int)current + (int)Marshal.SizeOf(typeof(IntPtr)));
}
return foundClients;
}
public static uint StringIPAddressToUInt32(string ip)
{
// convert string IP to uint IP e.g. "1.2.3.4" -> 16909060
IPAddress i = System.Net.IPAddress.Parse(ip);
byte[] ipByteArray = i.GetAddressBytes();
uint ipUint = (uint)ipByteArray[0] << 24;
ipUint += (uint)ipByteArray[1] << 16;
ipUint += (uint)ipByteArray[2] << 8;
ipUint += (uint)ipByteArray[3];
return ipUint;
}
public static string UInt32IPAddressToString(uint ip)
{
// convert uint IP to string IP e.g. 16909060 -> "1.2.3.4"
IPAddress i = new IPAddress(ip);
string[] ipArray = i.ToString().Split('.');
return ipArray[3] + "." + ipArray[2] + "." + ipArray[1] + "." + ipArray[0];
}
[DllImport("dhcpsapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern uint DhcpEnumSubnetClients(
string ServerIpAddress,
uint SubnetAddress,
ref uint ResumeHandle,
uint PreferredMaximum,
out IntPtr ClientInfo,
ref uint ElementsRead,
ref uint ElementsTotal
);
}
}
回答by t0mm13b
Would using arp -a
do the trick...on my machine the output I get is:
会用arp -a
做的伎俩......在我的机器上,我得到的输出是:
I have the mac/ip address replaced by bogus values to show the results...
我将 mac/ip 地址替换为虚假值以显示结果...
C:\Documents and Settings\Tom>arp -a Interface: 10.203.24.196 --- 0xf0007 Internet Address Physical Address Type 10.203.24.198 02-50-f3-10-14-06 dynamic C:\Documents and Settings\Tom>
By shelling out using System.Diagnostics.Process
, you can redirect the output to an input stream and read from it...
通过使用System.Diagnostics.Process
,您可以将输出重定向到输入流并从中读取...
Hope this helps, Best regards, Tom.
希望这会有所帮助,最好的问候,汤姆。