6

DHCP Win32 Apiの一部をC#に変換したので、PowerShellからを使用できます。

$definition = @"
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Net;

namespace Dhcpsapi
{

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

    [StructLayout(LayoutKind.Sequential)]
    public struct DHCP_BINARY_DATA
    {
        public uint DataLength;
        public IntPtr Data;
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct DHCP_IP_ADDRESS
    {
        public UInt32 IPAddress;
    }

    [StructLayout(LayoutKind.Explicit, Size=8)]
    public struct SearchInfo
    {
        [FieldOffset(0)]
        public DHCP_IP_ADDRESS ClientIpAddress;
        [FieldOffset(0)]
        public DHCP_BINARY_DATA ClientHardwareAddress;
        [FieldOffset(0)]
        public IntPtr ClientName; //LPWSTR
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DHCP_SEARCH_INFO
    {
        public DHCP_SEARCH_INFO_TYPE SearchType;
        public SearchInfo SearchInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DATE_TIME
    {
        public UInt32 dwLowDateTime;
        public UInt32 dwHighDateTime;

        public DateTime ToDateTime()
        {
            if (dwHighDateTime == 0 && dwLowDateTime == 0)
            {
                return DateTime.MinValue;
            }
            if (dwHighDateTime == int.MaxValue && dwLowDateTime == UInt32.MaxValue)
            {
                return DateTime.MaxValue;
            }
            return DateTime.FromFileTime((((long)dwHighDateTime) << 32) | dwLowDateTime);
        }
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct DHCP_HOST_INFO
    {
        public uint IpAddress;
        public string NetBiosName;
        public string HostName;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct DHCP_CLIENT_INFO
    {
        public uint ClientIpAddress;
        public uint 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 static class PS
    {

        [DllImport("Dhcpsapi.dll")]
        public static extern uint DhcpGetClientInfo(
            [MarshalAs(UnmanagedType.LPWStr)]
            string ServerIpAddress,
            [MarshalAs(UnmanagedType.Struct)]
            ref DHCP_SEARCH_INFO SearchInfo,
            out IntPtr ClientInfo);

        [DllImport("dhcpsapi.dll", SetLastError=true)]
        public static extern void DhcpRpcFreeMemory(IntPtr BufferPointer);
    }
}
"@

Add-Type -TypeDefinition $definition -PassThru

今、私はPowerShellからこれを使用しようとしています:

$dsi = New-Object dhcpsapi.DHCP_SEARCH_INFO
$dsi.SearchType = [Dhcpsapi.DHCP_SEARCH_INFO_TYPE]::DhcpClientIpAddress
$ipa = [System.Net.IPAddress]::Parse("10.4.3.101")
$ip = [UInt32][System.Net.IPAddress]::NetworkToHostOrder([int][System.BitConverter]::ToUInt32($ipa.GetAddressBytes(), 0))

# $ip is now 168035173
$dsi.SearchInfo.ClientIpAddress.IPAddress = $ip

#however $dsi.SearchInfo.ClientIpAddress.IPAddress is 0
$dsi.SearchInfo.ClientIpAddress.IPAddress

その実行後、$ dsi.SearchInfo.ClientIpAddress.IPAddressは、予想どおり168035173ではなく0になります。なぜこれが発生するのですか(C#から期待どおりに機能します)、これを機能させる方法は?

4

2 に答える 2

4

SearchInfoは構造体であるため、これを行うと次のようになります。

#however $dsi.SearchInfo.ClientIpAddress.IPAddress is 0
$dsi.SearchInfo.ClientIpAddress.IPAddress

次に、SearchInfoのコピーを作成し、そのコピーで値が変更されます。構造体ごとに、構造体を変更してから、割り当てる必要があります。

$clientIpAddress = $dsi.SearchInfo.ClientIpAddress
$clientIpAddress.IPAddress = $ip

$searchInfo = $dsi.SearchInfo
$searchInfo.ClientIpAddress = $clientIpAddress

$dsi.SearchInfo = $searchInfo
于 2012-10-31T15:47:45.647 に答える
2

問題は、参照型ではなく、値型である構造体を使用していることです。PowerShell演算子を介してこれらのメンバーにアクセスする'.'と、その構造体メンバーのコピーが返され、値の割り当てはそのコピーで行われ、変更しようとしているオブジェクトにはなりません。

これを示す小さな例を次に示します。

> add-type @"
namespace TestStructs {
    public struct Inner {
        public int i;
    };
    public class Outer {
        public Inner i;
    }
}
"@
$s = new-object TestStructs.Outer

メンバーとして構造体Outerを持つクラスを作成しました。値を割り当てようとすると、0のままで、表示されている動作が得られます。Inneri

> $s.i.i
0

> $s.i.i = 6

> $s.i.i
0

これを回避する方法は、構造体全体を割り当てることです。したがって、この単純なケースでは、新しい構造体を作成し、値を設定してから、変更するオブジェクトに割り当てることができます。

> $new_inner = new-object TestStructs.Inner
> $new_inner.i
0

> $new_inner.i = 6
> $new_inner.i
6

> $s.i = $new_inner
> $s.i.i
6

私はこれを行うためにいくつかの速記を使用することができます:

> $s.i = new-object TestStructs.Inner -prop @{ i = 7 }
> $s.i.i
7

ただし、構造体に多くの値がある場合、これは実用的ではない可能性があります。したがって、一時的な値に保存して、次のように再割り当てすることもできます。

> $s.i = &{ $temp = $s.i; $temp.i = 10; $temp }

H:\
> $s.i.i
10
于 2012-10-31T17:36:00.703 に答える