Сценарий
Я хотел бы видеть вывод команд PowerShell, которые выполняются внутри метода объекта, таким же образом, как я вижу их «вживую/когда они происходят», когда они не находятся внутри объекта.
Примеры
Чтобы проиллюстрировать нежелательную разницу, я покажу 2 скрипта, первый показывает вывод команды, второй нет. Оба запускаются путем открытия powershell, перехода в их каталог и запуска с помощью./<scriptname>.ps1
- Рассмотрите
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.
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>`
}
}
- Линия:
Write-Output (lxrun /install /y)
Результирующий вывод:(нет вывода)
- Линия:
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 .
- Линия:
Write-Host (lxrun /install /y) | Out-Host
Результат: тот же, что и в попытке 2.
- Линия:
Write-Host (lxrun /install /y) | Out-Default
Результат: тот же, что и в попытке 2.
- Линия:
Write-Host (lxrun /install /y) | Out-String
Результат: тот же, что и в попытке 2
- Линия:
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
- Линия:
write-verbose (lxrun /install /y) -Verbose
Результирующий вывод: такой же, как в пункте 6 (за исключением строки, в которой произошла ошибка, с параметром -Verbose)
- Линия:
(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 . ```
- Линия:
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
- Линия:
Write-Verbose -Message lxrun /install /y
Результат: тот же, что и в попытке 9
- Линия:
Write-Verbose -Message (lxrun /install /y) -Verbose
Результирующий вывод: такой же, как и в попытке 9 (за исключением строки, в которой произошла ошибка, с параметром -Verbose)
- На основевопрос и ответы, связанные в комментариях, я изменил скрипт следующим образом:
# 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()
Это «решает»/исправляет проблему, но я предпочитаю более глубокое понимание. Поэтому, если кто-то может объяснить:
- Почему добавляются дополнительные символы
null
иspace
, когда команда выполняется из/в объекте? Я был бы очень признателен. - Найдено лучшее решение, как это можно сделать в той же строке, что и команда, не вызывая самописный метод.