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
CodePudding user response:
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[]])