P/Invoke with DHCP management API

S

Steve

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: System.TypeLoadException. Does
anybody have experience working with this API from C# or know of some
documentation/examples? Thanks in advance. steve.
 
W

Willy Denoyette [MVP]

Steve said:
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: System.TypeLoadException. Does
anybody have experience working with this API from C# or know of some
documentation/examples? Thanks in advance. steve.

A "TypeLoadException" is not directly related to this API, could you please
post your code?

Willy.
 
S

Steve

here's a link to the API I'm trying to use:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dhcp/dhcp/dhcpcreateclientinfo.asp

Here's the structures and static api methods from my c# class:

//The DHCP_BINARY_DATA structure defines an opaque blob of binary data.
[StructLayout(LayoutKind.Sequential)]
public struct DHCP_BINARY_DATA
{
public UInt32 DataLength; //Specifies the size of Data, in bytes
public byte[] Data; //Pointer to an opaque blob of byte (binary)
data
}

//The DHCP_HOST_INFO structure defines information on a DHCP server
(host).
[StructLayout(LayoutKind.Sequential)]
public struct DHCP_HOST_INFO
{
public UInt32 IpAddress; //DHCP_IP_ADDRESS value that contains the
IP address of the DHCP server.
public StringBuilder NetBiosName; //Unicode string that contains the
Netbios name of the DHCP server.
public StringBuilder HostName; //Unicode string that contains the
network name of the DHCP server.
}

// The DATE_TIME structure defines a 64-bit integer value that
contains a date/time, expressed
// as the number of ticks (100-nanosecond increments) since 12:00
midnight, January 1, 1 C.E. in
// the Gregorian calendar.
[StructLayout(LayoutKind.Sequential)]
public struct DATE_TIME
{
public UInt32 dwLowDateTime; //Specifies the lower 32 bits of the
time value.
public UInt32 dwHighDateTime; //Specifies the upper 32 bits of the
time value
}

//The DHCP_CLIENT_INFO structure defines a client information record
used by the DHCP server.
[StructLayout(LayoutKind.Sequential)]
public struct DHCP_CLIENT_INFO
{
public UInt32 ClientIpAddress;
public UInt32 SubnetMask;
public DHCP_BINARY_DATA ClientHardwareAddress;
public StringBuilder ClientName;
public StringBuilder ClientComment;
public DATE_TIME ClientLeaseExpires;
public DHCP_HOST_INFO OwnerHost;
};

[DllImport("dhcpsapi.dll")]
static extern UInt32 CreateClientInfo(char[] ServerIpAddress,
DHCP_CLIENT_INFO ci);

[DllImport("dhcpsapi.dll")]
static extern UInt32 DeleteClientInfo(char[] ServerIpAddress,
DHCP_CLIENT_INFO ci);
#endregion
 
W

Willy Denoyette [MVP]

A bunch of API declarations is of little help here, what I wan't is the call
that throws and the callstack.

Willy.
 
S

Steve

I've been fighting with this a little more in my free time. I've made
some progress such that I can create a lease now. I'm currently
struggling with two issues that I know of. I'll mention the first
issue for now.

Getting a structure back from a win api call. i've tried different
variations of the following code but nothing works. The function call
does not return an error result or throw an exception so I'm stuck.
The DHCP_CLIENT_INFO structure passed back from GetClientInfo always
contains only null values. I'm having the same issue with other
functions to I'm assuming that I'm not managing output parameters
properly.

Here's are the c++ functions:

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;

typedef struct _DHCP_CLIENT_INFO {
DHCP_IP_ADDRESS ClientIpAddress;
DHCP_IP_MASK SubnetMask;
DHCP_CLIENT_UID ClientHardwareAddress;
LPWSTR ClientName;
LPWSTR ClientComment;
DATE_TIME ClientLeaseExpires;
DHCP_HOST_INFO OwnerHost;
} DHCP_CLIENT_INFO,
*LPDHCP_CLIENT_INFO;

DWORD DHCP_API_FUNCTION DhcpGetClientInfo(
DHCP_CONST WCHAR* ServerIpAddress,
DHCP_CONST DHCP_SEARCH_INFO* SearchInfo,
LPDHCP_CLIENT_INFO* ClientInfo
);

and now for the c#:

[DllImport("dhcpsapi.dll")]
static extern UInt32
DhcpGetClientInfo([MarshalAs(UnmanagedType.LPWStr)]String
ServerIpAddress, ref DHCP_CLIENT_SEARCH_IP_ADDRESS si, ref
DHCP_CLIENT_INFO ci);

public enum DHCP_SEARCH_INFO_TYPE: int
{
DhcpClientIpAddress=0,
DhcpClientHardwareAddress=1,
DhcpClientName=2
}

[StructLayout(LayoutKind.Sequential)]
public struct DHCP_CLIENT_SEARCH_IP_ADDRESS
{
public int SearchType;
public UInt32 ClientIpAddress;
};

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
public struct DHCP_CLIENT_INFO
{
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;
};

public UInt32 GetClientInfoByIpAddress(string ServerIpAddress,string
ClientIpAddress)
{
DHCP_CLIENT_SEARCH_IP_ADDRESS SearchInfo = new
DHCP_CLIENT_SEARCH_IP_ADDRESS();

SearchInfo.SearchType = (int)DHCP_SEARCH_INFO_TYPE.DhcpClientIpAddress;
SearchInfo.ClientIpAddress = ConvertIPStringToNumeric(ClientIpAddress);

DHCP_CLIENT_INFO ClientInfo = new DHCP_CLIENT_INFO();

UInt32 DHCPResult=0;
try
{
DHCPResult = DhcpGetClientInfo(new
String(ServerIpAddress.ToCharArray()),
ref SearchInfo, ref ClientInfo);
}
catch (Exception ex)
{
throw new Exception("Error searching for client lease:
"+ex.Message+"\nError code: "+DHCPResult.ToString(),ex);
}

// ClientInfo values are all null or empty here!!
return DHCPResult;
}
 
S

Steve

I figured it out. I needed to use an IntPtr for out parameters and
then marshal the structure. On to the next function... boy it takes a
long time to write code to call a few win32 functions! Somebody should
write a .net assembly with the common win32 functions and sell it.

steve.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top