Wie behält man das Ausgabeformat von Powershell-Befehlen bei, die von einem Objekt ausgeführt werden?

Wie behält man das Ausgabeformat von Powershell-Befehlen bei, die von einem Objekt ausgeführt werden?

Szenario

Ich möchte die Ausgabe von Powershell-Befehlen sehen, die innerhalb einer Methode eines Objekts ausgeführt werden, und zwar auf die gleiche Weise, wie ich sie „live/wenn sie stattfinden“ sehe, wenn sie sich nicht innerhalb des Objekts befinden.

Beispiele

Um den unerwünschten Unterschied zu veranschaulichen, zeige ich zwei Skripte, das erste zeigt die Ausgabe des Befehls, das zweite nicht. Beide werden ausgeführt, indem man Powershell öffnet, zu ihrem Verzeichnis navigiert und mit./<scriptname>.ps1

  1. Beim Inhalt berücksichtigen scriptA.ps1:
lxrun /install /y

Dies führt zum gewünschten Ergebnis:

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.ps1mit Inhalt:
# 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()

Es wird überhaupt keine Ausgabe angezeigt.

Versuche

Alle Versuche werden innerhalb des folgenden Skripts in der folgenden Zeile unternommen:<command here>

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

Resultierende Ausgabe: (keine Ausgabe)


  1. Linie:
Write-Host (lxrun /install /y)

Ergebnis: Korrekter Inhalt, aber lesbare Textformatierung verloren/geändert:

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. Linie:
Write-Host (lxrun /install /y) | Out-Host

Resultierende Ausgabe: dieselbe wie bei Versuch 2.

  1. Linie:
Write-Host (lxrun /install /y) | Out-Default

Resultierende Ausgabe: dieselbe wie bei Versuch 2.

  1. Linie:
Write-Host (lxrun /install /y) | Out-String

Resultierende Ausgabe: dieselbe wie in Versuch 2

  1. Linie:
write-verbose (lxrun /install /y)

Resultierende Ausgabe: (keine Ausgabe)

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. Linie:
write-verbose (lxrun /install /y) -Verbose

Resultierende Ausgabe: wie in 6 (außer wenn in der Zeile, in der der Fehler auftritt, -Verbose enthalten ist)


  1. Linie:
(lxrun /install /y) | Write-Host

Ergebnis: Besser lesbar, aber immer noch nicht das Normale

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. Linie:
Write-Verbose -Message (lxrun /install /y)

Resultierende Ausgabe:

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. Linie:
Write-Verbose -Message lxrun /install /y

Resultierende Ausgabe: dieselbe wie in Versuch 9

  1. Linie:
Write-Verbose -Message (lxrun /install /y) -Verbose

Resultierende Ausgabe: dieselbe wie in Versuch 9 (außer wenn in der Zeile, in der der Fehler auftritt, -Verbose enthalten ist)

  1. Bezogen aufdie in den Kommentaren verlinkten Fragen und Antwortenhabe ich das Skript wie folgt geändert:
# 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()

das beim Ausführen mit dem Parameter -Verbose aufgerufen wird: ./example.ps1 -Verbose. Es gibt einen schwarz-gelben Text zurück:

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:

Wobei, soweit ich verstanden habe, das Param()enthalten ist, um das Argument weiterzugeben/aufzunehmen -Verbose, und das[CmdletBinding()] ermöglicht die Let-Bindung auf die Art und Weise, wie es ein Skript cmdlettut, statt auf die „normale“ Art und Weise, wie es ein Skript tut.Ich muss noch verstehen, was dieser Unterschied ist/bedeutet. Und die Formatierung ist mit dieser Write-Verbose-Implementierung noch nicht korrekt/erwünscht.

Frage

Wie schreibe ich die Ausgabe eines Befehls ohne Verzögerung in das Powershell-Terminal, ohne die ursprüngliche Formatierung zu verlieren (wie bei scriptA.ps1)?

Notiz

Man könnte einen Parser bauen, aber ich denke, es gibt möglicherweise effizientere und schnellere Lösungen, die ich noch nicht gefunden habe.

Antwort1

Am Ende stellte sich heraus, dass das Schreiben eines Parsers eine schnellere Lösung war (hinsichtlich der Erstellung, nicht [unbedingt] hinsichtlich der Laufzeit), da mein Suchverfahren (noch) nicht untersucht hatte, warum und wie die Befehle write..usw. die Ausgabe (das Format) geändert haben.

# 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()

Dies „löst“/behebt das Problem, aber ich bevorzuge ein tieferes Verständnis. Wenn es also jemand erklären kann:

  1. Ich wäre sehr dankbar dafür, dass bei der Ausführung eines Befehls von/in einem Objekt die zusätzlichen nullund Zeichen hinzugefügt werden.space
  2. Eine bessere Lösung findet sich, indem man es in der gleichen Zeile des Kommandos macht, ohne eine selbstgeschriebene Methode aufzurufen.

verwandte Informationen