PInvoke 从指针到结构的编组值
PInvoke marshal value from pointer to struct
我想从 Dhcpsapi.dll.
调用方法 DhcpEnumSubnets()
https://docs.microsoft.com/en-us/windows/win32/api/dhcpsapi/nf-dhcpsapi-dhcpenumsubnets
CsWin32 自动生成了调用该方法所需的方法和结构。
https://github.com/microsoft/CsWin32
这是我的例子:
public static unsafe List<string> DhcpEnumSubnets(string serverAddress)
{
uint resumeHandle = 0;
uint preferredMaximum = 65536;
DHCP_IP_ARRAY* enumInfo = null;
List<string> subnets = new();
while (PInvoke.DhcpEnumSubnets(serverAddress,
ref resumeHandle,
preferredMaximum,
ref enumInfo,
out uint elementsRead,
out uint elementsTotal).IsEqual(DhcpErrorCode.SUCCESS))
{
try
{
DHCP_IP_ARRAY info = enumInfo[0];
for (uint j = 0; j < info.NumElements; j++)
{
uint nativeSubnetAddress = info.Elements[j];
var subnetAddress = DhcpHelper.NativeIpAddressToString(nativeSubnetAddress);
subnets.Add(subnetAddress);
}
}
finally
{
DhcpRpcFreeMemory(enumInfo);
}
}
return subnets;
}
我被告知要编写 2 个 for 循环来生成完整的项目,然后适当地释放它们。
try
{
for (uint i = 0; i < elementsRead; i++)
{
DHCP_IP_ARRAY info = enumInfo[i];
for (uint j = 0; j < info.NumElements; j++)
{
uint nativeSubnetAddress = info.Elements[j];
var subnetAddress = DhcpHelper.NativeIpAddressToString(nativeSubnetAddress);
subnets.Add(subnetAddress);
}
}
}
finally
{
for (uint i = 0; i < elementsRead; i++)
{
DhcpRpcFreeMemory(enumInfo[i].Elements);
}
DhcpRpcFreeMemory(enumInfo);
}
CsWin32 自动生成这个:
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#pragma warning disable CS1591, CS1573, CS0465, CS0649, CS8019, CS1570, CS1584, CS1658
namespace Microsoft.Windows.Sdk
{
using global::System;
using global::System.Diagnostics;
using global::System.Runtime.CompilerServices;
using global::System.Runtime.InteropServices;
/// <content>
/// Contains extern methods from "DHCPSAPI.dll".
/// </content>
internal static partial class PInvoke
{
/// <inheritdoc cref = "DhcpEnumSubnets(PCWSTR, uint *, uint, DHCP_IP_ARRAY**, uint *, uint *)"/>
internal static unsafe uint DhcpEnumSubnets(string ServerIpAddress, ref uint ResumeHandle, uint PreferredMaximum, ref DHCP_IP_ARRAY*EnumInfo, out uint ElementsRead, out uint ElementsTotal)
{
fixed (uint *ElementsTotalLocal = &ElementsTotal)
{
fixed (uint *ElementsReadLocal = &ElementsRead)
{
fixed (DHCP_IP_ARRAY**EnumInfoLocal = &EnumInfo)
{
fixed (uint *ResumeHandleLocal = &ResumeHandle)
{
fixed (char *ServerIpAddressLocal = ServerIpAddress)
{
uint __result = PInvoke.DhcpEnumSubnets(ServerIpAddressLocal, ResumeHandleLocal, PreferredMaximum, EnumInfoLocal, ElementsReadLocal, ElementsTotalLocal);
return __result;
}
}
}
}
}
}
/// <summary>The DhcpEnumSubnets function returns an enumerated list of subnets defined on the DHCP server.</summary>
/// <param name = "ServerIpAddress">Unicode string that specifies the IP address or hostname of the DHCP server.</param>
/// <param name = "ResumeHandle">Pointer to a <a href = "https://docs.microsoft.com/previous-versions/windows/desktop/dhcp/dhcp-server-management-type-definitions">DHCP_RESUME_HANDLE</a> value that identifies the enumeration operation. Initially, this value should be zero, with a successful call returning the handle value used for subsequent enumeration requests. For example, if <i>PreferredMaximum</i> is set to 100, and 200 subnet addresses are stored on the server, the resume handle can be used after the first 100 subnets are retrieved to obtain the next 100 on a subsequent call, and so forth.</param>
/// <param name = "PreferredMaximum">Specifies the preferred maximum number of subnet addresses to return. If the number of remaining unenumerated options is less than this value, then that amount will be returned.</param>
/// <param name = "EnumInfo">Pointer to a <a href = "https://docs.microsoft.com/windows/desktop/api/dhcpsapi/ns-dhcpsapi-dhcp_ip_array">DHCP_IP_ARRAY</a> structure that contains the subnet IDs available on the DHCP server. If no subnets are defined, this value will be null.</param>
/// <param name = "ElementsRead">Pointer to a <b>DWORD</b> value that specifies the number of subnet addresses returned in <i>EnumInfo</i>.</param>
/// <param name = "ElementsTotal">Pointer to a <b>DWORD</b> value that specifies the number of subnets defined on the DHCP server that have not yet been enumerated.</param>
/// <returns>This function returns <b>ERROR_SUCCESS</b> upon a successful call. If a call is made with the same <i>ResumeHandle</i> value and all items on the server have been enumerated, this method returns <b>ERROR_NO_MORE_ITEMS</b> with <i>ElementsRead</i> and <i>ElementsTotal</i> set to 0. Otherwise, it returns one of the <a href = "/previous-versions/windows/desktop/dhcp/dhcp-server-management-api-error-codes">DHCP Server Management API Error Codes</a>.</returns>
/// <remarks>
/// <para><see href = "https://docs.microsoft.com/windows/win32/api//dhcpsapi/nf-dhcpsapi-dhcpenumsubnets">Learn more about this API from docs.microsoft.com</see>.</para>
/// </remarks>
[DllImport("DHCPSAPI", ExactSpelling = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern unsafe uint DhcpEnumSubnets(PCWSTR ServerIpAddress, uint *ResumeHandle, uint PreferredMaximum, DHCP_IP_ARRAY**EnumInfo, uint *ElementsRead, uint *ElementsTotal);
}
}
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#pragma warning disable CS1591, CS1573, CS0465, CS0649, CS8019, CS1570, CS1584, CS1658
namespace Microsoft.Windows.Sdk
{
using global::System;
using global::System.Diagnostics;
using global::System.Runtime.CompilerServices;
using global::System.Runtime.InteropServices;
/// <summary>The DHCP_IP_ARRAY structure defines an array of IP addresses.</summary>
/// <remarks>
/// <para><see href = "https://docs.microsoft.com/windows/win32/api//dhcpsapi/ns-dhcpsapi-dhcp_ip_array">Learn more about this API from docs.microsoft.com</see>.</para>
/// </remarks>
internal partial struct DHCP_IP_ARRAY
{
/// <summary>Specifies the number of IP addresses in <b>Elements</b>.</summary>
internal uint NumElements;
/// <summary>Pointer to a list of <a href = "https://docs.microsoft.com/previous-versions/windows/desktop/dhcp/dhcp-server-management-type-definitions">DHCP_IP_ADDRESS</a> values.</summary>
internal unsafe uint *Elements;
}
}
2 个 for 循环的方法对我不起作用,我是不是遗漏了什么?
第一个代码示例对我有用,我不确定这真的是调用此方法的正确方法吗?
这部分让我感到困惑:
DHCP_IP_ARRAY info = enumInfo[0]
像数组一样访问指针是否有效?基本上我将值从指针传递给结构。这是否将所有需要的值分配给结构?一个指针在 index 0
中是否只保存一个值?我想知道这是否可以与 dhcpsapi.dll 的其他方法一起使用,index 0
会给我所有结果吗?
根据DhcpEnumSubnets函数,EnumInfo
是一个指向DHCP_IP_ARRAY结构的指针,可以像访问数组一样访问指针。
是的,这会将所有需要的值分配给 sruct,指针是否只在索引 0 中保存一个值取决于 DhcpEnumSubnets
函数。
我想从 Dhcpsapi.dll.
调用方法 DhcpEnumSubnets()https://docs.microsoft.com/en-us/windows/win32/api/dhcpsapi/nf-dhcpsapi-dhcpenumsubnets
CsWin32 自动生成了调用该方法所需的方法和结构。
https://github.com/microsoft/CsWin32
这是我的例子:
public static unsafe List<string> DhcpEnumSubnets(string serverAddress)
{
uint resumeHandle = 0;
uint preferredMaximum = 65536;
DHCP_IP_ARRAY* enumInfo = null;
List<string> subnets = new();
while (PInvoke.DhcpEnumSubnets(serverAddress,
ref resumeHandle,
preferredMaximum,
ref enumInfo,
out uint elementsRead,
out uint elementsTotal).IsEqual(DhcpErrorCode.SUCCESS))
{
try
{
DHCP_IP_ARRAY info = enumInfo[0];
for (uint j = 0; j < info.NumElements; j++)
{
uint nativeSubnetAddress = info.Elements[j];
var subnetAddress = DhcpHelper.NativeIpAddressToString(nativeSubnetAddress);
subnets.Add(subnetAddress);
}
}
finally
{
DhcpRpcFreeMemory(enumInfo);
}
}
return subnets;
}
我被告知要编写 2 个 for 循环来生成完整的项目,然后适当地释放它们。
try
{
for (uint i = 0; i < elementsRead; i++)
{
DHCP_IP_ARRAY info = enumInfo[i];
for (uint j = 0; j < info.NumElements; j++)
{
uint nativeSubnetAddress = info.Elements[j];
var subnetAddress = DhcpHelper.NativeIpAddressToString(nativeSubnetAddress);
subnets.Add(subnetAddress);
}
}
}
finally
{
for (uint i = 0; i < elementsRead; i++)
{
DhcpRpcFreeMemory(enumInfo[i].Elements);
}
DhcpRpcFreeMemory(enumInfo);
}
CsWin32 自动生成这个:
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#pragma warning disable CS1591, CS1573, CS0465, CS0649, CS8019, CS1570, CS1584, CS1658
namespace Microsoft.Windows.Sdk
{
using global::System;
using global::System.Diagnostics;
using global::System.Runtime.CompilerServices;
using global::System.Runtime.InteropServices;
/// <content>
/// Contains extern methods from "DHCPSAPI.dll".
/// </content>
internal static partial class PInvoke
{
/// <inheritdoc cref = "DhcpEnumSubnets(PCWSTR, uint *, uint, DHCP_IP_ARRAY**, uint *, uint *)"/>
internal static unsafe uint DhcpEnumSubnets(string ServerIpAddress, ref uint ResumeHandle, uint PreferredMaximum, ref DHCP_IP_ARRAY*EnumInfo, out uint ElementsRead, out uint ElementsTotal)
{
fixed (uint *ElementsTotalLocal = &ElementsTotal)
{
fixed (uint *ElementsReadLocal = &ElementsRead)
{
fixed (DHCP_IP_ARRAY**EnumInfoLocal = &EnumInfo)
{
fixed (uint *ResumeHandleLocal = &ResumeHandle)
{
fixed (char *ServerIpAddressLocal = ServerIpAddress)
{
uint __result = PInvoke.DhcpEnumSubnets(ServerIpAddressLocal, ResumeHandleLocal, PreferredMaximum, EnumInfoLocal, ElementsReadLocal, ElementsTotalLocal);
return __result;
}
}
}
}
}
}
/// <summary>The DhcpEnumSubnets function returns an enumerated list of subnets defined on the DHCP server.</summary>
/// <param name = "ServerIpAddress">Unicode string that specifies the IP address or hostname of the DHCP server.</param>
/// <param name = "ResumeHandle">Pointer to a <a href = "https://docs.microsoft.com/previous-versions/windows/desktop/dhcp/dhcp-server-management-type-definitions">DHCP_RESUME_HANDLE</a> value that identifies the enumeration operation. Initially, this value should be zero, with a successful call returning the handle value used for subsequent enumeration requests. For example, if <i>PreferredMaximum</i> is set to 100, and 200 subnet addresses are stored on the server, the resume handle can be used after the first 100 subnets are retrieved to obtain the next 100 on a subsequent call, and so forth.</param>
/// <param name = "PreferredMaximum">Specifies the preferred maximum number of subnet addresses to return. If the number of remaining unenumerated options is less than this value, then that amount will be returned.</param>
/// <param name = "EnumInfo">Pointer to a <a href = "https://docs.microsoft.com/windows/desktop/api/dhcpsapi/ns-dhcpsapi-dhcp_ip_array">DHCP_IP_ARRAY</a> structure that contains the subnet IDs available on the DHCP server. If no subnets are defined, this value will be null.</param>
/// <param name = "ElementsRead">Pointer to a <b>DWORD</b> value that specifies the number of subnet addresses returned in <i>EnumInfo</i>.</param>
/// <param name = "ElementsTotal">Pointer to a <b>DWORD</b> value that specifies the number of subnets defined on the DHCP server that have not yet been enumerated.</param>
/// <returns>This function returns <b>ERROR_SUCCESS</b> upon a successful call. If a call is made with the same <i>ResumeHandle</i> value and all items on the server have been enumerated, this method returns <b>ERROR_NO_MORE_ITEMS</b> with <i>ElementsRead</i> and <i>ElementsTotal</i> set to 0. Otherwise, it returns one of the <a href = "/previous-versions/windows/desktop/dhcp/dhcp-server-management-api-error-codes">DHCP Server Management API Error Codes</a>.</returns>
/// <remarks>
/// <para><see href = "https://docs.microsoft.com/windows/win32/api//dhcpsapi/nf-dhcpsapi-dhcpenumsubnets">Learn more about this API from docs.microsoft.com</see>.</para>
/// </remarks>
[DllImport("DHCPSAPI", ExactSpelling = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern unsafe uint DhcpEnumSubnets(PCWSTR ServerIpAddress, uint *ResumeHandle, uint PreferredMaximum, DHCP_IP_ARRAY**EnumInfo, uint *ElementsRead, uint *ElementsTotal);
}
}
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#pragma warning disable CS1591, CS1573, CS0465, CS0649, CS8019, CS1570, CS1584, CS1658
namespace Microsoft.Windows.Sdk
{
using global::System;
using global::System.Diagnostics;
using global::System.Runtime.CompilerServices;
using global::System.Runtime.InteropServices;
/// <summary>The DHCP_IP_ARRAY structure defines an array of IP addresses.</summary>
/// <remarks>
/// <para><see href = "https://docs.microsoft.com/windows/win32/api//dhcpsapi/ns-dhcpsapi-dhcp_ip_array">Learn more about this API from docs.microsoft.com</see>.</para>
/// </remarks>
internal partial struct DHCP_IP_ARRAY
{
/// <summary>Specifies the number of IP addresses in <b>Elements</b>.</summary>
internal uint NumElements;
/// <summary>Pointer to a list of <a href = "https://docs.microsoft.com/previous-versions/windows/desktop/dhcp/dhcp-server-management-type-definitions">DHCP_IP_ADDRESS</a> values.</summary>
internal unsafe uint *Elements;
}
}
2 个 for 循环的方法对我不起作用,我是不是遗漏了什么? 第一个代码示例对我有用,我不确定这真的是调用此方法的正确方法吗? 这部分让我感到困惑:
DHCP_IP_ARRAY info = enumInfo[0]
像数组一样访问指针是否有效?基本上我将值从指针传递给结构。这是否将所有需要的值分配给结构?一个指针在 index 0
中是否只保存一个值?我想知道这是否可以与 dhcpsapi.dll 的其他方法一起使用,index 0
会给我所有结果吗?
根据DhcpEnumSubnets函数,EnumInfo
是一个指向DHCP_IP_ARRAY结构的指针,可以像访问数组一样访问指针。
是的,这会将所有需要的值分配给 sruct,指针是否只在索引 0 中保存一个值取决于 DhcpEnumSubnets
函数。