設想
我希望看到在物件的方法內部執行的 powershell 命令的輸出,就像當它們不在物件內部時我看到它們「即時/發生時」一樣。
例子
為了說明不必要的差異,我將顯示 2 個腳本,第一個腳本顯示 commnad 的輸出,第二個腳本則不顯示。兩者都是透過開啟 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 以 a 的方式進行綁定cmdlet
,而不是腳本的「正常」方式。我仍然需要了解這種差異是什麼/意味著什麼。且此 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
- 怎麼可以和指令在同一行完成,而不呼叫自己寫的方法,找到了更好的解決方案。