1

I have a powershell script with an added type:

Add-Type -TypeDefinition @'
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    [Serializable]
    public struct  md_size {
                [MarshalAs(UnmanagedType.U4)]  public uint md_type;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]  public byte[] md_data;
            } ;
}
...'

I need to convert this to a byte array, to send it on the wire.

I have tried using the BinaryFormatter:

$in = ... (object of type md_size)
$mstr = New-Object System.IO.MemoryStream
$fmt = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$fmt .Serialize($mstr , $in)
$result = $mstr.GetBuffer()

And I expect to get an array of size of 260 back, but I get a size of 256, which I don't quite understand.

How can I convert my struct into a byte[] array?

Will I Am
  • 2,614
  • 3
  • 35
  • 61

1 Answers1

1

If I run your md_size struct through a BinaryFormatter like in your example I get 405 bytes of output, not sure why you only see 256 - try calling GetBuffer() again and see if there's more.

If you just want a byte-for-byte copy of the struct value, you can allocate a marshalled memory region, then copy the struct value to that and finally copy it to a byte array from there, like in this answer:

$Marshal = [System.Runtime.InteropServices.Marshal]

try {
  # Calculate the length of the target array
  $length  = $Marshal::SizeOf($in)
  $bytes   = New-Object byte[] $length

  # Allocate memory for a marshalled copy of $in
  $memory  = $Marshal::AllocHGlobal($length)
  $Marshal.StructureToPtr($in, $memory, $true)
  # Copy the value to the output byte array
  $Marshal.Copy($memory, $bytes, 0, $length)
}
finally {
  # Free the memory we allocated for the struct value
  $Marshal.FreeHGlobal($memory)
}
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206