Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PowerShell在c#结构中设置值_C#_Powershell_Pinvoke - Fatal编程技术网

使用PowerShell在c#结构中设置值

使用PowerShell在c#结构中设置值,c#,powershell,pinvoke,C#,Powershell,Pinvoke,我已将一些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 : i

我已将一些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
$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之后,它的值是0,而不是我预期的168035173。为什么会发生这种情况(它按照C#的预期工作)以及如何使其工作?

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

问题是您使用的是结构,它是值类型,而不是引用类型。当通过PowerShell
“.
运算符访问这些成员时,它会返回该结构成员的副本,值赋值发生在该副本上,并且不会将其放入您试图修改的对象中

下面是一个较小的示例,演示了这一点:

> add-type @"
namespace TestStructs {
    public struct Inner {
        public int i;
    };
    public class Outer {
        public Inner i;
    }
}
"@
$s = new-object TestStructs.Outer
我创建了一个类
Outer
,它有一个
internal
结构作为成员
I
。如果我尝试分配该值,则会得到您看到的行为,该行为保持为0:

> $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