シナリオ
オブジェクトのメソッド内で実行される PowerShell コマンドの出力を、オブジェクト内にないときに「ライブ/実行時」に表示されるのと同じ方法で表示したいと思います。
例
望ましくない違いを説明するために、2つのスクリプトを示します。最初のスクリプトはコマンドの出力を表示し、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()]
cmdlet
スクリプトが行う「通常の」方法ではなく、a が行う方法で let バインディングを有効にします。その違いが何であるか/何を意味するかをまだ理解する必要があります。また、この Write-Verbose 実装では、フォーマットがまだ正しくなく、望ましくありません。
質問
遅延なく、元のフォーマットを失うことなく ( の場合のように)、PowerShell ターミナルにコマンドの出力を書き込むにはどうすればよいですかscriptA.ps1
?
注記
パーサーを構築することもできますが、私がまだ見つけていない、より効率的で高速なソリューションがあるのではないかと思います。
答え1
結局、私の検索手順では、write..
etc などのコマンドが出力 (形式) を変更する理由と方法について (まだ) 調べていなかったため、パーサーを作成する方が高速 (ビルド的には高速、実行時には必ずしも高速ではない) なソリューションであることが判明しました。
# 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
- 独自に作成したメソッドを呼び出さずに、コマンドと同じ行で実行する方法があれば、より良い解決策が見つかります。