0

Looking for a way to assign byte array to an object - tried using -as operator with no luck. (Targeting PowerShell version 5.1)

$CSharpCode = @"
using System;
namespace TestStructure
{
    public struct TestStructure3
    {
       public Byte Field1;
       public Byte Field2;
       public UInt32 Field3;
       public UInt32 Field4;
    }

    public struct TestStructure2
    {
       public UInt32 Field1;
       public UInt32 Field2;
    }

    public struct TestStructure1
    {
       public UInt16 Field1;
       public UInt16 Field2;
       public TestStructure2 Field3;
       public TestStructure3 Field4;
    }
}
"@

Add-Type -TypeDefinition $CSharpCode

[byte[]]$BytesArray = 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22

$MyObject = $BytesArray -as [TestStructure.TestStructure1]
  • that last call fails, $MyObject is $null
4
  • 1
    [byte[]]$BytesArray = 1, ... works fine. Is your real question "How do I create an instance of my struct type from a binary array"? Commented Mar 28, 2022 at 15:51
  • Create an object of TestStructure1, then enumerate its properties: $obj = [TestStructure.TestStructure1]::new(); $obj.PSObject.Properties.ForEach{ $_ }. Assign bytes to property values based on their size. Commented Mar 28, 2022 at 15:52
  • @MathiasR.Jessen - yes, my question is "How do I create an instance of my struct type from a binary array"? I was able to construct something using code from stackoverflow.com/questions/2871/… - added ByteArrayToNewStuff() method and calling it with $BytesArray - not sure if this is correct. Commented Mar 28, 2022 at 16:28
  • @ssa that should work too, I've posted an answer below that also uses PtrToStructure(). Commented Mar 28, 2022 at 16:51

1 Answer 1

3

PowerShell doesn't natively translate between byte arrays and initialized instances of blittable types, but you can write a small utility function to take care of it like this:

function ConvertTo-Struct
{
  # Only accept struct types (sealed value types that are neither primitive nor enum)
  param(
    [Parameter(Mandatory = $true)]
    [ValidateScript({ $_.IsValueType -and $_.IsSealed -and -not($_.IsPrimitive -or $_.IsEnum) })]
    [Type]$TargetType,

    [Parameter(Mandatory = $true)]
    [byte[]]$BinaryData
  )

  # Start by calculating minimum size of the underlying memory allocation for the new struct
  $memSize = [System.Runtime.InteropServices.Marshal]::SizeOf([type]$TargetType)

  # Make sure user actually passed enough data to initialize struct
  if($memSize -gt $BinaryData.Length){
    Write-Error "Not enough binary data to create an instance of [$($TargetType.FullName)]"
    return
  }

  # now we just need some unmanaged memory in which to create our struct instance
  $memPtr = [IntPtr]::Zero
  try {
    $memPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($memSize)

    # copy byte array to allocated unmanaged memory from previous step
    [System.Runtime.InteropServices.Marshal]::Copy($BinaryData, 0, $memPtr, $memSize)

    # then marshal the new memory region as a struct and return
    return [System.Runtime.InteropServices.Marshal]::PtrToStructure($memPtr, [type]$TargetType)
  }
  finally {
    # and finally remember to clean up the allocated memory
    if($memPtr -ne [IntPtr]::Zero){
      [System.Runtime.InteropServices.Marshal]::FreeHGlobal($memPtr)
    }
  }
}

Now that we've gotten that squared away, let's put it to use:

$testStructure1 = ConvertTo-Struct -TargetType ([TestStructure.TestStructure1]) -BinaryData (1..24 -as [byte[]])
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, this works. What is the license for this code? (Can it be used without attribution?)
@ssa I just wrote up this example for this post, so CC BY-SA 4.0 (share and derive as you see fit, but attribute to this post if used as-is) :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.