Почему вывод текста из одного CmdLet отформатирован, а вывод текста из другого - нет? - PullRequest
0 голосов
/ 14 февраля 2020

Я написал 2 командлета для преобразования между GUID и эквивалентом Oracle Guid, строк, которые он отображает для столбцов RAW, используемых для хранения GUID. Первый, Convert-GuidToRaw, принимает строковый параметр GUID и выводит необработанную строку:

var raw = GuidConverter.Core.GuidConverter.ToRaw(Input);
WriteObject(raw);

Где raw имеет тип string. Когда я запускаю этот командлет, я получаю простой и простой вывод строки:

PS D:\SANRAL\NRA2> New-Guid | Convert-GuidToRaw                                                                  
DD8386EE09231A43B7731880CCAD6B87
PS D:\SANRAL\NRA2>

Мой другой командлет, Convert-RawToGuid, принимает строковый параметр RAW, представляющий GUID, и выводит необработанный GUID:

var guid = GuidConverter.Core.GuidConverter.FromRaw(Input);
WriteObject(guid);

Где guid имеет тип Guid. Когда я запускаю этот командлет, я получаю вывод в формате таблицы:

PS D:\SANRAL\NRA2> Convert-RawToGuid DD8386EE09231A43B7731880CCAD6B87

Guid
----
ee8683dd-2309-431a-b773-1880ccad6b87


PS D:\SANRAL\NRA2>

В обоих случаях я выводю один объект, а не список, и в обоих случаях объект легко представляется простой строкой. Почему я получаю табличный вывод при возврате типа Guid?

Возможно, стоит отметить, что командлет Convert-GuidToRaw с его простым, неформатированным строковым выводом выглядит неправильно написать в конвейер. Оба командлета принимают один параметр из конвейера. Я ожидал бы, что этот конвейер командлетов ниже выведет GUID, когда вместо этого последний командлет в конвейере пока ищет ввод:

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:

Почему Convert-RawToGuid не получает "конвейерную" строку из Convert-GuidToRaw? Переключение порядка конвейера, как показано ниже, приводит к ожидаемому поведению:

PS C:\WINDOWS\system32> Convert-RawToGuid F3BD9411DE8E4F4BBCACECFCED6D305D | Convert-GuidToRaw
F3BD9411DE8E4F4BBCACECFCED6D305D
PS C:\WINDOWS\system32>

Командлет Convert-RawToGuid выглядит следующим образом:

[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);
    }
}

Командлет Convert-GuidToRaw выглядит следующим образом:

[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);
    }
}

1 Ответ

1 голос
/ 14 февраля 2020

Часть 1

В обоих случаях я вывожу один объект, а не список, и в обоих случаях объект легко представляется простой строкой. Почему я получаю табличный вывод при возврате типа Guid?

Когда команда в интерактивном сеансе возвращает неназначенное значение, PowerShell передает его по умолчанию Команда форматирования для генерации текст перед записью на консоль. PowerShell предварительно настроен с кучей команд форматирования для некоторых указанных типов c, и System.Guid является одним из этих типов.

Например:

PS> [Guid]::NewGuid()

Guid
----
ee737b6f-7f68-4015-8841-1278b37a6420

Стандартные средства форматирования для различных типов настраиваются в * .Format.ps1 xml файлах в PowerShell 5.1 и включаются в исходный код PowerShell 6 и далее в соответствии с О Format.ps1 xml

В PowerShell 5.1 конфигурация форматера по умолчанию для System.Guid находится в $PSHOME\DotNetTypes.format.ps1xml и выглядит следующим образом:

<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>

, поэтому вы получаете таблицу с одним столбцом, который содержит свойство Guid.

Вы получите точно такой же результат, если сделаете это:

PS> [Guid]::NewGuid() | Format-Table -Property "Guid"

Guid
----
ee737b6f-7f68-4015-8841-1278b37a6420

и если вы захотите захватить результат по умолчанию Команда форматирования в строковую переменную (например, для записи в файл журнала) вы можете сделать это:

PS> $text = [Guid]::NewGuid() | Out-String
PS> $text

Guid
----
ee737b6f-7f68-4015-8841-1278b37a6420

Часть 2

Почему Convert- RawToGuid не получает "конвейерную" строку из Convert-GuidToRaw? Переключение порядка конвейера, как показано ниже, приводит к ожидаемому поведению:

Я не могу воспроизвести вашу проблему, но мне подходит следующее (с предупреждением, что я не смог найти библиотека с классом GuidConverter.Core.GuidConverter, поэтому я предполагаю, что это частная реализация, и вместо этого я использую строку по умолчанию - например: "024673b5-9c65-447a-be87-dae5f11f5142"). Вы можете попробовать это локально и посмотреть, получите ли вы тот же результат или проблему, о которой вы сообщили, и go оттуда ...

  • Создайте новое решение C# для библиотеки классов, используя. Net Framework 4.7.2 в Visual Studio
  • Добавьте ссылку на пакет NuGet для Microsoft.PowerShell.5.1.ReferenceAssemblies
  • Добавьте приведенный ниже код в новый файл класса и создайте проект:
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);
        }
    }

}

Если я создаю этот код, я могу ссылаться на него из PowerShell, и работает следующий код:

PS> Import-Module ".\MyCmdlet.dll"
PS> New-Guid | Convert-GuidToRaw | Convert-RawToGuid

Guid
----
15591624-44c9-4c55-acd7-22b7a2d0bee0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...