32

I have some PowerShell code that is using a COM API. I am getting a Type Mismatch error when I pass in a byte array. Here is how I am creating the array, as well as some type information

PS C:\> $bytes = Get-Content $file -Encoding byte
PS C:\> $bytes.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS C:\> $bytes[0].GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Byte                                     System.ValueType

Poking around with the API, I have found that it is looking for a Byte[] with a base type of System.Array.

PS C:\> $r.data.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Byte[]                                   System.Array

PS C:\> $r.data[0].gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Byte                                     System.ValueType

What I am trying to do is convert $bytes into the same type as $r.data. For some reason, $bytes is getting created as an Object[]. How can I cast it to a Byte[]?

Andy Schneider
  • 8,516
  • 6
  • 36
  • 52

5 Answers5

45

This answer is for the question with no context. I'm adding it because of search results.

[System.Byte[]]::CreateInstance([System.Byte],<Length>)
26

There are probably even more ways, but these are the ones I can think of:

Direct array initialization:

[byte[]] $b = 1,2,3,4,5
$b = [byte]1,2,3,4,5
$b = @([byte]1,2,3,4,5)
$b = [byte]1..5

Create a zero-initialized array

$b = [System.Array]::CreateInstance([byte],5)
$b = [byte[]]::new(5)        # Powershell v5+
$b = New-Object byte[] 5
$b = New-Object -TypeName byte[] -Args 5

And if you ever want an array of byte[] (2-D array)

# 5 by 5
[byte[,]] $b = [System.Array]::CreateInstance([byte],@(5,5)) # @() optional for 2D and 3D
[byte[,]] $b = [byte[,]]::new(5,5)

Additionally:

# 3-D
[byte[,,]] $b = [byte[,,]]::new(5,5,5)
[byte[,]] $b = [System.Array]::CreateInstance([byte],5,5,5)
YenForYang
  • 2,998
  • 25
  • 22
  • You should double-check your options and verify which one creates an array of bytes and which one creates an array of objects. – Carsten Mar 03 '22 at 12:45
25

In PS 5.1, this:

[System.Byte[]]::CreateInstance(<Length>)

didn't work for me. So instead I did:

new-object byte[] 4

which resulted in an empty byte[4]:

0
0
0
0
Andrew
  • 5,839
  • 1
  • 51
  • 72
21

Cast it to a byte array:

[byte[]]$bytes = Get-Content $file -Encoding byte
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • This doesn't work -- PowerShell complains that you can't convert `System.Object[]` to `System.Byte[]`. – BrainSlugs83 Jun 28 '18 at 02:49
  • @BrainSlugs83 I tested this before posting and it does work, provided you don't omit the `-Encoding Byte` argument. If it doesn't work for you you may want to post a new question with a [mcve] including your PowerShell version and the full error message. – Ansgar Wiechers Jun 28 '18 at 06:55
0

FWIW if you want to encode just any arbitrary string as a byte[] array:

$foo = "This is a string"
[byte[]]$bar = $foo.ToCharArray()
Dragoon
  • 723
  • 6
  • 13
  • This will work for ASCII only. Once you have a `char` that does not fit to 8 bits, you lose information by casting it to `byte` this way. The `char` is 16-bit in .NET. – Martin Prikryl Sep 24 '20 at 06:29