472,789 Members | 1,023 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,789 software developers and data experts.

DHCP with P/Invoke

Hello,

I'm working on an application to allow our network team to use a small
application to make DHCP reservations on our Microsoft DHCP Server.

The problem is you have to use P/Invoke to do it, and from what I've
found on the web and in this newsgroup is that it's not easy, however I
believe it can/has been done.

At the moment I'm just trying to find out information about an existing
reservation but I'm getting stuck. I read the newsgroup article
'P/Invoke with DHCP management API' which got me started but the last
comment made on 2006-01-01 didn't make sense to me and I can't get the
damn thing to work, in my test console app.

Here is the code I am using, could someone point me in the right
direction please?:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace DHCP
{
class Program
{
static void Main(string[] args)
{
String ServerIpAddress = "192.168.0.250";

UInt32 DHCPResult = 0;
try
{
DhcpApi.DHCP_SEARCH_INFO searchInfo = new
DhcpApi.DHCP_SEARCH_INFO();
DhcpApi.DHCP_SEARCH_INFO_TYPE searchInfoType =
DhcpApi.DHCP_SEARCH_INFO_TYPE.DhcpClientIpAddress;

searchInfo.SearchType = searchInfoType;
searchInfo.ClientIpAddress =
DhcpApi.ConvertIPAddress("192.168.0.5");

DhcpApi.DHCP_CLIENT_INFO clientInfo = new
DhcpApi.DHCP_CLIENT_INFO();

DHCPResult = DhcpApi.DhcpGetClientInfo(ServerIpAddress,
ref searchInfo, ref clientInfo);
Console.WriteLine(DHCPResult.ToString() + " Client
Info: " + clientInfo.ClientName);
}
catch (Exception ex)
{

Console.WriteLine("******************************* *********************************************");
Console.WriteLine("ERROR: \t" + DHCPResult.ToString());
Console.WriteLine("MESSAGE: \t" + ex.Message);
Console.WriteLine();
Console.WriteLine("FULL DETAILS:");
Console.WriteLine(ex.ToString());

Console.WriteLine("******************************* *********************************************");
}

Console.ReadKey(true);
}
}

public class DhcpApi
{
/// <summary>
/// The DhcpGetClientInfo function returns information about a
specific DHCP client.
/// </summary>
/// <param name="ServerIpAddress">[in] Unicode string that
specifies the IP address of the DHCP server.</param>
/// <param name="SearchInfo">[in] DHCP_SEARCH_INFO structure
that contains the parameters for the search. </param>
/// <param name="ClientInfo">[out] Pointer to a
DHCP_CLIENT_INFO structure that contains information describing the DHCP
client that most closely matches the provided search parameters. If no
client is found, this parameter will be null.</param>
/// <returns>This function returns ERROR_SUCCESS upon a
successful call. Otherwise, it returns one of the DHCP Server Management
API Error Codes.</returns>
[DllImport("dhcpsapi.dll", SetLastError = true,CharSet =
CharSet.Unicode)]
public static extern UInt32
DhcpGetClientInfo([MarshalAs(UnmanagedType.LPWStr)]String
ServerIpAddress, ref DHCP_SEARCH_INFO SearchInfo, ref DHCP_CLIENT_INFO
ClientInfo);

/// <summary>
/// The DHCP_SEARCH_INFO_TYPE enumeration defines the set of
possible
/// attributes used to search DHCP client information records.
/// </summary>
public enum DHCP_SEARCH_INFO_TYPE : int
{
/// <summary>
/// The search will be performed against the assigned DHCP
client IP address, represented as a 32-bit unsigned integer value.
/// </summary>
DhcpClientIpAddress = 0,
/// <summary>
/// The search will be performed against the MAC address of
the DHCP client network interface device, represented as a
DHCP_BINARY_DATA structure.
/// </summary>
DhcpClientHardwareAddress = 1,
/// <summary>
/// The search will be performed again the DHCP client's
network name, represented as a Unicode string.
/// </summary>
DhcpClientName = 2
}

/// <summary>
/// The DHCP_SEARCH_INFO structure defines the DHCP client record
/// data used to search against for particular server operations.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DHCP_SEARCH_INFO
{
// typedef struct _DHCP_CLIENT_SEARCH_INFO {
// DHCP_SEARCH_INFO_TYPE SearchType;
// union {
// DHCP_IP_ADDRESS ClientIpAddress;
// DHCP_CLIENT_UID ClientHardwareAddress;
// LPWSTR ClientName;
// } SearchInfo;
//} DHCP_SEARCH_INFO, *LPDHCP_SEARCH_INFO;

public DHCP_SEARCH_INFO_TYPE SearchType;
public UInt32 ClientIpAddress;
}
/// <summary>
/// The DHCP_CLIENT_INFO structure defines a client information
record
/// used by the DHCP server.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DHCP_CLIENT_INFO
{
//
************************************************** **************************
// DHCP_IP_ADDRESS Specifies an IP address, with the first
byte containing
// the first number in the address, the second byte
containing the second
// number, the third byte containing the third number, and
the last byte
// containing the last number in the address. For example,
the address
// 192.1.1.10 is represented as 11000000 00000001 00000001
00001010 (binary),
// or 3221291274 (decimal).
//
************************************************** **************************
public UInt32 ClientIpAddress;
public UInt32 SubnetMask;
public DHCP_BINARY_DATA ClientHardwareAddress;
[MarshalAs(UnmanagedType.LPWStr)]
public String ClientName;
[MarshalAs(UnmanagedType.LPWStr)]
public String ClientComment;
public DATE_TIME ClientLeaseExpires;
public DHCP_HOST_INFO OwnerHost;
}
}
}
I'm also hoping to implement the following API functions in the future,
if anyone has any pointers on these as well! ;o):

DhcpGetClientInfo
DhcpDeleteClientInfo
DhcpCreateClientInfo
DhcpSetClientInfo
DhcpEnumSubnetClients

Cheers,

Richard W.
--
Google First. Ask Later.
Sep 1 '06 #1
5 7474
Richard,
>At the moment I'm just trying to find out information about an existing
reservation but I'm getting stuck. I read the newsgroup article
'P/Invoke with DHCP management API' which got me started but the last
comment made on 2006-01-01 didn't make sense to me and I can't get the
damn thing to work, in my test console app.
What he's saying is that you have to change the method signature to

public static extern UInt32 DhcpGetClientInfo(String ServerIpAddress,
ref DHCP_SEARCH_INFO SearchInfo, out IntPtr ClientInfo);

and then make the calling code

IntPtr pClientInfo;
DHCPResult = DhcpApi.DhcpGetClientInfo(ServerIpAddress, ref
searchInfo, out pClientInfo);
if (DHCPResult == 0 && pClientInfo != IntPtr.Zero)
{
DHCP_CLIENT_INFO clientInfo =
(DHCP_CLIENT_INFO)Marshal.PtrToStructure(pClientIn fo,
typeof(DHCP_CLIENT_INFO));
...
}

Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Sep 3 '06 #2
Mattias,
What he's saying is that you have to change the method signature to

public static extern UInt32 DhcpGetClientInfo(String ServerIpAddress,
ref DHCP_SEARCH_INFO SearchInfo, out IntPtr ClientInfo);

and then make the calling code

IntPtr pClientInfo;
DHCPResult = DhcpApi.DhcpGetClientInfo(ServerIpAddress, ref
searchInfo, out pClientInfo);
if (DHCPResult == 0 && pClientInfo != IntPtr.Zero)
{
DHCP_CLIENT_INFO clientInfo =
(DHCP_CLIENT_INFO)Marshal.PtrToStructure(pClientIn fo,
typeof(DHCP_CLIENT_INFO));
...
}
Thank you very much, that's got it working a treat. :o)

I can move on now, I'm sure I'll have more questions about this how
topic so watch this thread people!! ;o)

Cheers,

Richard
Sep 4 '06 #3
Mattias,

You mention in the thread 'Problem Creating Structures with P/Invoke'
that when using the struct DHCP_IP_ARRAY that you should dereference the
pointer to retrieve the addresses with Marshal.Copy().

I've been trying all morning to do it, but can't seem to get my head
round it. Could you offer some assistance again please? I get the code
below working but I'm trying to retrieve a list of the subnets returned
not just the number.

....
{
DHCP_IP_ARRAY ips = new DHCP_IP_ARRAY();
uint nr = 0, total = 0, resumeHandle = 0;

DhcpEnumSubnets("192.168.0.250", ref resumeHandle, 1000, ref ips,
ref nr, ref total);

Console.WriteLine("Elements read {0} of total {1}", nr, total);
}

[StructLayout(LayoutKind.Sequential)]
public struct DHCP_IP_ARRAY
{
public uint NumElements;
public IntPtr IPAddresses;
}

[DllImport("dhcpsapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint DhcpEnumSubnets(
string ServerIP,
ref uint resumeHandle,
uint PerferedMax,
ref DHCP_IP_ARRAY ipAddresses,
ref uint ElementsRead,
ref uint ElementsTotal);

Cheers,

Richard
Sep 4 '06 #4
Richard,
>You mention in the thread 'Problem Creating Structures with P/Invoke'
that when using the struct DHCP_IP_ARRAY that you should dereference the
pointer to retrieve the addresses with Marshal.Copy().

I've been trying all morning to do it, but can't seem to get my head
round it. Could you offer some assistance again please?
Looks like it's pretty much the same issue as in your last post. The
parameter is actually a pointer to a pointer to the struct. So try it
like this:
>[DllImport("dhcpsapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint DhcpEnumSubnets(
string ServerIP,
ref uint resumeHandle,
uint PerferedMax,
out IntPtr ipAddresses,
ref uint ElementsRead,
ref uint ElementsTotal);
If the argument comes back non-null, you can use
Marshal.PtrToStructure or Marshal.Copy to retrieve the DHCP_IP_ARRAY
data.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Sep 4 '06 #5
Mattias,
Looks like it's pretty much the same issue as in your last post. The
parameter is actually a pointer to a pointer to the struct. So try it
like this:
>[DllImport("dhcpsapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint DhcpEnumSubnets(
string ServerIP,
ref uint resumeHandle,
uint PerferedMax,
out IntPtr ipAddresses,
> ref uint ElementsRead,
ref uint ElementsTotal);

If the argument comes back non-null, you can use
Marshal.PtrToStructure or Marshal.Copy to retrieve the DHCP_IP_ARRAY
data.
Thank you, I've got this bit working, although I had to work hard to get
it back into a decent format.

If there are any glaring mistakes then let me know, but the code below
does work for me. Also if any one has a better (more efficient method)
for converting the UInt32 IP Address back in to a dot notation IP
Address then please post here! ;o)

Now onto the next bit. Anyone got some pointers on searching for a
MAC/Hardware Address on the DHCP server using DhcpGetClientInfo? I can
retrieve the ClientInfo structure back if I search for the IP Address
but not if I use the hardware address or client name.

Code for others who search this thread, I'll stick it up on the
pinvoke.net (wiki) when I get a chance:

static void Main()
{
String ServerIpAddress = "192.168.0.250";
UInt32 DHCPResult = 0;

IntPtr ips;
uint nr = 0;
uint total = 0;
uint resumeHandle = 0;

if (DHCPResult == 0)
{
DHCPResult = DhcpEnumSubnets(ServerIpAddress, ref resumeHandle,
1000, out ips, ref nr, ref total);

DHCP_IP_ARRAY ipArray =
(DHCP_IP_ARRAY)Marshal.PtrToStructure(ips, typeof(DHCP_IP_ARRAY));

int size = (int)ipArray.NumElements;
IntPtr outArray = ipArray.IPAddresses;
DHCP_IP_ADDRESS[] ipAddressArray = new DHCP_IP_ADDRESS[size];
IntPtr current = outArray;
for (int i = 0; i < size; i++)
{
ipAddressArray[i] = new DHCP_IP_ADDRESS();
Marshal.PtrToStructure(current, ipAddressArray[i]);
Marshal.DestroyStructure(current, typeof(DHCP_IP_ADDRESS));
current = (IntPtr)((int)current +
Marshal.SizeOf(ipAddressArray[i]));

Console.WriteLine("{0}",
UInt32IPAddressToString(ipAddressArray[i].IPAddress));
}
Marshal.FreeCoTaskMem(outArray);

Console.WriteLine("Elements read {0} of total {1}", nr, total);

}
else
{
int code = 0;
unchecked
{
code = (int)DHCPResult;
}
Win32Exception winex = new Win32Exception(code);
Console.WriteLine(winex.NativeErrorCode + " : " + winex.Message);
}
}

[DllImport("dhcpsapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint DhcpEnumSubnets(
string ServerIpAddress,
ref uint ResumeHandle,
uint PreferredMaximum,
out IntPtr EnumInfo,
ref uint ElementsRead,
ref uint ElementsTotal
);

[StructLayout(LayoutKind.Sequential)]
public struct DHCP_IP_ARRAY
{
public uint NumElements;
public IntPtr IPAddresses;
}

/// This is a custom type/class
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DHCP_IP_ADDRESS
{
public UInt32 IPAddress;
}

public static string UInt32IPAddressToString(UInt32 ipAddress)
{
IPAddress ipA = new IPAddress(ipAddress);
string[] sIp = ipA.ToString().Split('.');

return sIp[3] + "." + sIp[2] + "." + sIp[1] + "." + sIp[0];
}

Regards,

Richard
Sep 6 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Leszek Gruszka | last post by:
How to get static IP adresses from DHCP?
5
by: Steve | last post by:
Hi Folks, I'm trying to create a c# class to manage a DHCP subnet using the win api (dhcpsapi.dll). Currently I can't even instanciate my class, instead I receive the error:...
3
by: jmd.msdn | last post by:
Hello. Is it possible to obtain programmatically, with .net 2.0 + C# + Active Directory or P/Invoke, a list of the authorized current DHCP servers in a forest/domain ? And, if the above...
2
by: WhatHappend | last post by:
I have converted a .Net 1.0 application to .Net 2.0 and the web service invocations have delay of around 10seconds on each intial access. After the first access subsequent access are fast (After a...
0
by: GHUM | last post by:
Hello, I need to get a list of active leases on a windows dhcp server. Experts from Microsoft statet: """" A: Go to the Address leases of each scope in the DHCP snap-in and dump the leases...
1
by: Screenbert | last post by:
After finding nothing anywhere in google I am posting this so everyone can benefit by it. The formating is not pretty since I copied it from my word document, but you should benefit by it. ...
0
by: screenbert | last post by:
Managing DHCP Servers using C# They said it was impossible. It couldn't be done. But you can in fact manage DHCP servers using C#. This includes creating and deleting Scopes, SuperScopes,...
7
by: ixeye | last post by:
Anybody else ever had a problem like this? Windows 2003 Domain with 180 machines, 21 of them with XP SP2 Laptop Wireless access to the domain, on three different WIFI AP. Randomly (and luckily...
7
by: =?Utf-8?B?VGhlTWFkSGF0dGVy?= | last post by:
Quick q: If I open a socket on my computer and eventualy the dhcp changes the address of my computer, what happens? Will it drop the connection? Thanks in advance for any help on the topic.
0
by: Rina0 | last post by:
Cybersecurity engineering is a specialized field that focuses on the design, development, and implementation of systems, processes, and technologies that protect against cyber threats and...
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: lllomh | last post by:
How does React native implement an English player?
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.