0

I am new to PowerShell and I have a one shot task to perform which must be done with PowerShell. This involves Active Directory as well. I need to add a new computer object into our AD and one of the attributes I must set at creation time is a 16 bytes binary value. I am getting as input a string which is an hexadecimal representation of the value I must set for the attribute.

I tried to input the value asis and it doesn't work. I tried escaping each byte with a backslash, it doesn't work neither.

How should I format the input for this to work with the New-ADComputer command? I am setting a bunch of other attributes successfully. When I remove this binary entry from my hashtable passed to the -OtherAttributes option it works fine. So, obviously a format problem. I found nothing about the expected format for such attributes.

Any hints? TIA.

EDIT 2018-06-05 19:44 EDT:

I tried converting the string to a byte array as follow:

Function Convert-Hex2ByteArray {
    [cmdletbinding()]

    param(
        [parameter(Mandatory=$true)]
        [String]
        $HexString
    )

    [byte[]] $Bytes = @(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)

    For($i=0; $i -lt $HexString.Length; $i+=2) {
        $Bytes[$i/2] = [convert]::ToByte($HexString.Substring($i, 2), 16)
    }

    $Bytes
}

(...)

$netbootGUID = Convert-Hex2ByteArray($args[$indiceArgs])
$otherAttributes.add( "netbootGUID", $netbootGUID )

(...)

New-ADComputer -Credential $cred -Server $ADhost -Path "CN=Computers,$baseDN" -SAMAccountName $sAMAccountName -Name $name-Instance 4 -OtherAttributes $otherAttributes

This leads to the following error (I apologize for my own translation since the original message is shown in French):

Many values were specified for an attribut which can only have one

Problem solved:

$netbootGUID = New-Object Guid $args[$indiceArgs]
$otherAttributs.add( "netbootGUID", $netbootGUID )

Did the trick.

Achille
  • 607
  • 1
  • 11
  • 23
  • 3
    where is your code? – Avshalom Jun 05 '18 at 14:35
  • The question is pretty much straight forward. Code will not add any further understanding since the question is about how you pass a binary value to New-ADComputer for AD to be updated correctly. Here is the line of code which is concerned: New-ADComputer -Credential $cred -Server $host -Path "CN=Computers,$baseDN" -SAMAccountName $sAMAccountName -Name $wsName -Instance 4 -OtherAttributes $otherAttributes where $otherAttributes is a hashtable which contains seven attributes, one of them being a binary attribute. When I remove the binary attribute from the hastable everything works fine. – Achille Jun 05 '18 at 15:27
  • What attribute and why does it need to be set in this particular manner? – Bill_Stewart Jun 05 '18 at 17:04
  • I didn't design the AD object I have to update. The only thing I know about it is it is a 16 bytes binary value. It is not to me to discuss if this design is good or not and if there is another way to go. It exists since many years and now I have to interface with it. – Achille Jun 05 '18 at 23:53

1 Answers1

2

Typically for binary storage you need to convert the string to a byte array:

$String = '3c6ef75eaa2c4b23992bbd65ac891917'
$ByteArray = [byte[]]$(for ($i = 0; $i -lt $String.Length; $i+=2) { [Convert]::ToByte($String.Substring($i,2), 16) })

To convert it back:

$NewString = -join $(foreach($Byte in $ByteArray) { $Byte.ToString('x2') })

If you want the characters upper case, specify 'X2' instead of 'x2'.


Since you're storing 16 byte values, I'll note that if you're storing GUIDs you may need to change the storage order since the order of bytes in a string representation of a GUID does not match the order of bytes in a byte representation of a GUID on an x86 system. Fortunately, there are built in functions for handling this conversion with the built-in System.Guid data type:

$GUID = 'f8d89eb2b49c4bfeab44a85ccdc4191a'
$ByteArray = [Guid]::new($GUID).ToByteArray()

And a constructor for converting back:

$NewGUID = [Guid]::new($ByteArray)

Whether or not you should use this method depends on exactly what property you're updating and whether or not the application(s) that will be using the property in question will correctly be handling the GUIDs or if they're just storing the GUID as raw bytes (which is incorrect but not surprising). You'll have to test by seeing what GUID your application sees and comparing it to the byte array in Active Directory to verify that it's correct.

For specifics on the byte ordering, see the documentation for Guid.ToByteArray():

Note that the order of bytes in the returned byte array is different from the string representation of a Guid value. The order of the beginning four-byte group and the next two two-byte groups is reversed, whereas the order of the last two-byte group and the closing six-byte group is the same. The example provides an illustration.

The reason for this is that a GUID is partially constructed from a series of integers of varying sizes, and the UUID standard specifies big endianness for those numbers. x86 computers are little-endian systems.

Bacon Bits
  • 30,782
  • 5
  • 59
  • 66
  • Basically what I tried after asking is very similar to what you suggest. I appended my code in my original post. – Achille Jun 05 '18 at 23:44