Reputation: 51094
I have written 2 cmdlets, for converting between GUIDs and Oracle's Guid equivalent, the strings it displays for RAW columns used to store GUIDs. The first, Convert-GuidToRaw
, accepts a GUID string param and outputs a raw string:
var raw = GuidConverter.Core.GuidConverter.ToRaw(Input);
WriteObject(raw);
Where raw
has type string
. When I run this cmdlet, I get a plain and simple string output:
PS D:\SANRAL\NRA2> New-Guid | Convert-GuidToRaw
DD8386EE09231A43B7731880CCAD6B87
PS D:\SANRAL\NRA2>
My other cmdlet, Convert-RawToGuid
, accepts a RAW string param representing a GUID and outputs a raw GUID:
var guid = GuidConverter.Core.GuidConverter.FromRaw(Input);
WriteObject(guid);
Where guid
has type Guid
. When I run this cmdlet, I get output formatted like a table:
PS D:\SANRAL\NRA2> Convert-RawToGuid DD8386EE09231A43B7731880CCAD6B87
Guid
----
ee8683dd-2309-431a-b773-1880ccad6b87
PS D:\SANRAL\NRA2>
In both cases I output a single object, not a list, and in both cases the object is easily represented by a simple string. Why do I get tabular output when I return a Guid
type?
It may be worth noting that the Convert-GuidToRaw
cmdlet, with its plain, un-formatted, string output, doesn't seem to properly write to the pipeline. Both cmdlets take one parameter, from the pipeline. I would expect this cmdlet pipeline below to output a GUID, when instead the last cmdlet in the pipeline is till looking for input:
PS C:\WINDOWS\system32> New-Guid | Convert-GuidToRaw | Convert-RawToGuid
cmdlet Convert-RawToGuid at command pipeline position 3
Supply values for the following parameters:
Input:
Why is Convert-RawToGuid
not getting a "pipelined" string from Convert-GuidToRaw
? Swapping the order of the pipeline as below, causes the expected behaviour:
PS C:\WINDOWS\system32> Convert-RawToGuid F3BD9411DE8E4F4BBCACECFCED6D305D | Convert-GuidToRaw
F3BD9411DE8E4F4BBCACECFCED6D305D
PS C:\WINDOWS\system32>
The Convert-RawToGuid
cmdlet looks like this:
[Cmdlet(VerbsData.Convert, "RawToGuid")]
public class ConvertRawToGuidCommand : System.Management.Automation.Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public string Input { get; set; }
protected override void ProcessRecord()
{
if (string.IsNullOrEmpty(Input) || Input.Length != 32)
{
throw new ArgumentException("Input must be a 32 character hex string");
}
var guid = GuidConverter.Core.GuidConverter.FromRaw(Input);
WriteObject(guid);
}
}
The Convert-GuidToRaw
cmdlet looks like this:
[Cmdlet(VerbsData.Convert, "GuidToRaw")]
public class ConvertGuidToRawCommand : System.Management.Automation.Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public Guid Input { get; set; }
protected override void ProcessRecord()
{
var raw = GuidConverter.Core.GuidConverter.ToRaw(Input);
WriteObject(raw);
}
}
Upvotes: 0
Views: 297
Reputation: 10075
Part 1
In both cases I output a single object, not a list, and in both cases the object is easily represented by a simple string. Why do I get tabular output when I return a Guid type?
When a command in an interactive session returns an unassigned value, PowerShell passes it to a default Format Command to generate the text before it's written to the console. PowerShell is pre-configured with a bunch of Format Commands for some specific types, and System.Guid is one of those types.
For example:
PS> [Guid]::NewGuid()
Guid
----
ee737b6f-7f68-4015-8841-1278b37a6420
The default formatters for various types are configured in *.Format.ps1xml files in PowerShell 5.1, and are baked into the source code from PowerShell 6 onwards as per About Format.ps1xml
In PowerShell 5.1, the default formatter configuration for System.Guid can be found in $PSHOME\DotNetTypes.format.ps1xml
and looks like this:
<View>
<Name>System.Guid</Name>
<ViewSelectedBy>
<TypeName>System.Guid</TypeName>
</ViewSelectedBy>
<TableControl>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Guid</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
so you get a table with a single column that contains the Guid
property.
You get exactly the same result if you do this:
PS> [Guid]::NewGuid() | Format-Table -Property "Guid"
Guid
----
ee737b6f-7f68-4015-8841-1278b37a6420
and if you want to capture the result of the default formatting command into a string variable (e.g. to write to a log file) you can do this:
PS> $text = [Guid]::NewGuid() | Out-String
PS> $text
Guid
----
ee737b6f-7f68-4015-8841-1278b37a6420
Part 2
Why is Convert-RawToGuid not getting a "pipelined" string from Convert-GuidToRaw? Swapping the order of the pipeline as below, causes the expected behaviour:
I'm not able to reproduce your issue, but the following works for me (with the caveat that I couldn't find a library with the the class GuidConverter.Core.GuidConverter
so I'm assuming it's a private implementation and I'm using the default string fomat instead - e.g. : "024673b5-9c65-447a-be87-dae5f11f5142"). You could try this locally and see if you get the same result or the issue you reported, and go from there...
using System;
using System.Management.Automation;
namespace MyCmdlet
{
[Cmdlet(VerbsData.Convert, "RawToGuid")]
public class ConvertRawToGuidCommand : Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public string Input { get; set; }
protected override void ProcessRecord()
{
if (string.IsNullOrEmpty(this.Input) || this.Input.Length != 36)
{
throw new ArgumentException("Input must be a 36 character hex string");
}
var guid = new Guid(this.Input);
WriteObject(guid);
}
}
[Cmdlet(VerbsData.Convert, "GuidToRaw")]
public class ConvertGuidToRawCommand : Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public Guid Input { get; set; }
protected override void ProcessRecord()
{
var raw = this.Input.ToString();
WriteObject(raw);
}
}
}
If I build this code I can reference it from PowerShell and the following code works:
PS> Import-Module ".\MyCmdlet.dll"
PS> New-Guid | Convert-GuidToRaw | Convert-RawToGuid
Guid
----
15591624-44c9-4c55-acd7-22b7a2d0bee0
Upvotes: 1