Как сохранить формат вывода команд Powershell, выполняемых из объекта?

Как сохранить формат вывода команд Powershell, выполняемых из объекта?

Сценарий

Я хотел бы видеть вывод команд PowerShell, которые выполняются внутри метода объекта, таким же образом, как я вижу их «вживую/когда они происходят», когда они не находятся внутри объекта.

Примеры

Чтобы проиллюстрировать нежелательную разницу, я покажу 2 скрипта, первый показывает вывод команды, второй нет. Оба запускаются путем открытия powershell, перехода в их каталог и запуска с помощью./<scriptname>.ps1

  1. Рассмотрите scriptA.ps1содержание:
lxrun /install /y

Что дает желаемый результат:

Warning: lxrun.exe is only used to configure the legacy Windows
Subsystem for Linux distribution. Distributions can be installed by
visiting the Windows Store: https://aka.ms/wslstore

This will install Ubuntu on Windows, distributed by Canonical and
licensed under its terms available here: https://aka.ms/uowterms

The legacy Windows Subsystem for Linux distribution is already
installed. 
  1. scriptB.ps1с содержанием:
# runs single command
Class Object{
    runCommand(){
        lxrun /install /y
    }
}

# create object
[Object] $object = [Object]::new()

# execute command in method runCommand() of [Object] object
$object.runCommand()

Который вообще не показывает никаких выходных данных.

Попытки

Все попытки производятся внутри следующего скрипта, в строке:<command here>

# runs single command
Class Object{
    runCommand(){
        `<command here>`
    }
}
  1. Линия:
Write-Output (lxrun /install /y)

Результирующий вывод:(нет вывода)


  1. Линия:
Write-Host (lxrun /install /y)

Результат: Правильное содержимое, но утрачено/изменено читаемое форматирование текста:

W a r n i n g :   l x r u n . e x e   i s   o n l y   u s e d   t o  
c o n f i g u r e   t h e   l e g a c y   W i n d o w s   S u b s y s
t e m   f o r   L i n u x   d i s t r i b u t i o n .       D i s t r
i b u t i o n s   c a n   b e   i n s t a l l e d   b y   v i s i t i
n g   t h e   W i n d o w s   S t o r e :       h t t p s : / / a k a
. m s / w s l s t o r e             T h i s   w i l l   i n s t a l l 
U b u n t u   o n   W i n d o w s ,   d i s t r i b u t e d   b y   C
a n o n i c a l   a n d   l i c e n s e d   u n d e r   i t s   t e r
m s   a v a i l a b l e   h e r e :         h t t p s : / / a k a . m
s / u o w t e r m s             T h e   l e g a c y   W i n d o w s  
S u b s y s t e m   f o r   L i n u x   d i s t r i b u t i o n   i s 
a l r e a d y   i n s t a l l e d . 
  1. Линия:
Write-Host (lxrun /install /y) | Out-Host

Результат: тот же, что и в попытке 2.

  1. Линия:
Write-Host (lxrun /install /y) | Out-Default

Результат: тот же, что и в попытке 2.

  1. Линия:
Write-Host (lxrun /install /y) | Out-String

Результат: тот же, что и в попытке 2

  1. Линия:
write-verbose (lxrun /install /y)

Результирующий вывод:(нет вывода)

Write-Verbose : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Message'.
Specified method is not supported.
At F:\path to example script\example.ps1:30 char:23
+         write-verbose (lxrun /install /y)
+                       ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Write-Verbose], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.WriteVerboseCommand
  1. Линия:
write-verbose (lxrun /install /y) -Verbose

Результирующий вывод: такой же, как в пункте 6 (за исключением строки, в которой произошла ошибка, с параметром -Verbose)


  1. Линия:
(lxrun /install /y) | Write-Host

Результат: лучше читается, но все еще не то

o   c o n f i g u r e   t h e   l e g a c y  W i n d o w s   S u b s y
s t e m   f o r   L i n u x   d i s t r i b u t i o n .


 D i s t r i b u t i o n s   c a n   b e   i n s t a l l e d   b y   v
i s i t i n g   t h e   W i n d o w s   S t o r e :


 h t t p s : / / a k a . m s / w s l s t o r e





 T h i s   w i l l   i n s t a l l   U b u n t u   o n   W i n d o w s
,   d i s t r i b u t e d   b y   C a n o n i c a l   a n d   l i c e
n s e d   u n d e r   i t s   t e r m s   a v a i l a b l e   h e r e
:


 h t t p s : / / a k a . m s / u o w t e r m s





 T h e   l e g a c y   W i n d o w s   S u b s y s t e m   f o r   L i
n u x   d i s t r i b u t i o n   i s   a l r e a d y   i n s t a l l
e d . ```
  1. Линия:
Write-Verbose -Message (lxrun /install /y)

Итоговый вывод:

Write-Verbose : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Message'. Specified method is not supported.
At G:/path to file\example.ps1:35 char:32
 +         Write-Verbose -Message (lxrun /install /y)
 +                                ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Write-Verbose], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.WriteVerboseCommand
  1. Линия:
Write-Verbose -Message lxrun /install /y

Результат: тот же, что и в попытке 9

  1. Линия:
Write-Verbose -Message (lxrun /install /y) -Verbose

Результирующий вывод: такой же, как и в попытке 9 (за исключением строки, в которой произошла ошибка, с параметром -Verbose)

  1. На основевопрос и ответы, связанные в комментариях, я изменил скрипт следующим образом:
# runs single command

#[CmdletBinding(SupportsShouldProcess=$true)]
[CmdletBinding()]
Param()
Class Object{    
    runCommand(){
        lxrun /install /y|Write-Verbose
    }
}

# create object
[Object] $object = [Object]::new()

# execute command in method runCommand() of [Object] object
$object.runCommand()

который вызывается с параметром -Verbose при запуске: ./example.ps1 -Verbose. Он возвращает черно-желтый текст:

VERBOSE: W a r n i n g :   l x r u n . e x e   i s   o n l y   u s e d   t o   >c o n f i g u r e   t h e
l e g a c y   W i n d o w s   S u b s y s t e m   f o r   L i n u x   d i s t >r i b u t i o n .
VERBOSE:
VERBOSE:
VERBOSE:  D i s t r i b u t i o n s   c a n   b e   i n s t a l l e d   b y   v >i s i t i n g   t h e
W i n d o w s   S t o r e :
VERBOSE:
VERBOSE:
VERBOSE:  h t t p s : / / a k a . m s / w s l s t o r e
VERBOSE:
VERBOSE:
VERBOSE:
VERBOSE:
VERBOSE:
VERBOSE:  T h i s   w i l l   i n s t a l l   U b u n t u   o n   W i n d o w s >,   d i s t r i b u t e d
b y   C a n o n i c a l   a n d   l i c e n s e d   u n d e r   i t s   t e r >m s   a v a i l a b l e
h e r e :
VERBOSE:
VERBOSE:
VERBOSE:  h t t p s : / / a k a . m s / u o w t e r m s
VERBOSE:
VERBOSE:
VERBOSE:
VERBOSE:
VERBOSE:
VERBOSE:  T h e   l e g a c y   W i n d o w s   S u b s y s t e m   f o r   L i >n u x
d i s t r i b u t i o n   i s   a l r e a d y   i n s t a l l e d .
VERBOSE:
VERBOSE:
VERBOSE:

Где, насколько я понял, Param()включено, чтобы передать/усвоить -Verboseаргумент, и[CmdletBinding()] позволяет выполнять связывание let так, как cmdletэто делает a, а не «нормальным» способом, как это делает скрипт.Мне все еще нужно понять, что это за разница/что это значит. И форматирование пока не является правильным/нежелательным в этой реализации Write-Verbose.

Вопрос

Как записать вывод команды в терминал PowerShell без задержки, не теряя исходного форматирования (как в случае с scriptA.ps1)?

Примечание

Можно было бы создать парсер, но я думаю, что могут быть более эффективные и быстрые решения, которые я пока не нашел.

решение1

В конце концов оказалось, что написание парсера было более быстрым (с точки зрения построения, но не [обязательно] с точки зрения времени выполнения) решением, поскольку моя процедура поиска (пока) не изучала, почему и как команды с write..и т. д. изменили вывод (формат).

# runs single command
Class Object{
    runCommand(){
        $output = (lxrun /install /y)
        Write-Host $this.parseOutput($output) # return formating back to "normal"
    }

    # removes null characters and then replaces triple spaces with enters.
    [String] parseOutput([String] $output){

        # first remove all nulls
        $output = $output.Replace(([char]0).ToString(),'')

        # then replace all triple occurrences of spaces with newlines
        $output = $output.Replace(([char]32+[char]32+[char]32).ToString(),"`n")

        return $output
    }

}

# create object
[Object] $object = [Object]::new()

# execute command in method runCommand() of [Object] object
$object.runCommand()

Это «решает»/исправляет проблему, но я предпочитаю более глубокое понимание. Поэтому, если кто-то может объяснить:

  1. Почему добавляются дополнительные символы nullи space, когда команда выполняется из/в объекте? Я был бы очень признателен.
  2. Найдено лучшее решение, как это можно сделать в той же строке, что и команда, не вызывая самописный метод.

Связанный контент