MicrosoftDocs / PowerShell-Docs

The official PowerShell documentation sources
https://learn.microsoft.com/powershell
Other
2.01k stars 1.58k forks source link

Format-Hex Updates #4532

Closed vexx32 closed 4 years ago

vexx32 commented 5 years ago

Issue Details

See https://github.com/PowerShell/PowerShell/pull/8674 for full details.

Summary

  1. In PS 6.2 and below, Format-Hex doesn't handle piped input as a single input (even if it's a single data type), and renders a completely separate block of output for every item input of the pipeline, regardless of the type of input.
  2. In PS 6.1 and below, Format-Hex only handles byte and string input. (Maybe others? The same as it was in v5, I don't recall the full amount). This was changed in 6.2 (I think; @iSazonov authored the PR that expanded the functionality) and it is now able to handle a larger variety of data types. (Essentially anything it can convert to byte data; strings, [char], [int], structs, etc., etc.)

With https://github.com/PowerShell/PowerShell/pull/8674 merged, Format-Hex:

Behavioural Details

Piped Input

A Primitive Value

  1. Each item is converted to bytes and collected into an input buffer.
  2. The type of the last InputObject is stored in a private field.
  3. If a new InputObject is received of the same type, it is converted to bytes and added to the buffer.
  4. If a new InputObject is received of a different type, the buffer is divided into 16-byte segments and each segment is sent to the success output stream as a ByteCollection. Then, the process restarts from the beginning.

System.IO.FileInfo

  1. If any data is in the primitives buffer, it is output as described above, the buffer is cleared, as well as the information on what the last type was (resetting the grouping logic).
  2. One ByteCollection object is emitted per 16 bytes of the file.
  3. All ByteCollection objects are tagged with the input file's path as their Label, which will group their output into a single table.
  4. Offset and Count are interpreted as applying to each file, the same way as they would be for -Path inputs.

String

  1. If any data is in the primitives buffer, it is output as described above, the buffer is cleared, as well as the information on what the last type was (resetting the grouping logic).
  2. All strings are handled on an individual basis (no grouping), and are converted into bytes according to the -Encoding parameter's value.
  3. One ByteCollection object is emitted per 16 bytes of the string, and each is tagged with the System.String type name and a shared random hexadecimal ID to ensure that each string is assigned a separate Label group.
  4. Offset and Count are interpreted as applying to each input string.

Array of Primitives

  1. If any data is in the primitives buffer, it is output as described above, the buffer is cleared, as well as the information on what the last type was (resetting the grouping logic).
  2. Each array is treated as a single "group", and will not be grouped with other items in the output.
  3. All items in the array are converted into a single chunk of bytes, which then is sliced according to Offset and Count.
  4. One ByteCollection object is emitted per 16 bytes, and each is tagged with the array's type and a shared random hexadecimal ID to ensure that each array is assigned a single Label group.

Examples

Jagged Input Example Jagged Input Incl. FileInfo Object Example

Output

If you plan on processing output from Format-Hex programmatically, note that the output mode is line-by-line; each ByteCollection created by the cmdlet only holds 16 bytes before creating a new object.

If you wish to handle specific segments of output when working with mixed input (as shown in the examples), you can use their .Label property to determine which ByteCollection objects belong together. Group-Object is one way to separate out the groupings into the groups displayed by the formatter, in order to be able to handle them separately.

For example, to collate all byte values for all input collections while retaining the grouping according to input object, you could do something like this:

$input |
    Format-Hex |
    Group-Object -Property Label |
    Select-Object -Property Label, @{ Name = "Bytes"; Expression = { $_.Group.Bytes } }

Version(s) of document impacted

Reason(s) for not selecting all version of documents

vexx32 commented 5 years ago

@sdwheeler updated the description with fleshed-out details from the PR. If you guys have any questions, let me know! πŸ’–