What is the default method invoked on a Write-Output object in Powershell?

I found strange behavior using powershell.

The output of only quotation marks is different from the result of the ToString () method called on the same object.

which method or property is called in

Write-Output "$a" 

This is the directory in which I run the example

 > PS C:\temp\testps> DIR Directory: C:\temp\testps Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 03/12/2010 11.21 8 1.txt -a--- 03/12/2010 11.21 8 2.txt -a--- 03/12/2010 11.21 8 3.txt 

Here I assign a collection of files to the $ q object

 PS C:\temp\testps> $q = Get-ChildItem . "*.txt" 

Now I want to print the file names, but I get unexpected output

 PS C:\temp\testps> foreach ($a in $q) {Write-Output $a} Directory: C:\temp\testps Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 03/12/2010 11.21 8 1.txt -a--- 03/12/2010 11.21 8 2.txt -a--- 03/12/2010 11.21 8 3.txt 

Putting quotes around the object name shows the correct behavior

 PS C:\temp\testps> foreach ($a in $q) {Write-Output "$a"} 1.txt 2.txt 3.txt 

This result is only for the first object. It seems that the entire DIR command is output to the first file name. Disassembled.

 PS C:\temp\testps> foreach ($a in $q) {Write-Output $a;break} Directory: C:\temp\testps Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 03/12/2010 11.21 8 1.txt 

The ToString () method behaves like a quoted object.

 PS C:\temp\testps> foreach ($a in $q) {Write-Output $a.ToString()} 1.txt 2.txt 3.txt 
+4
source share
2 answers

In the first case, the Write-Output $a object (System.IO.FileInfo) is formatted by the PowerShell formatting engine based on format data stored in $pshome\FileSystem.format.ps1xml . This is what really runs:

 Write-Output $a | Out-Default 

Out-Default is implicitly executed at the end of the pipeline, and this cmdlet does formatting based on formatting data.

In the case of "$a" , the ToString() view is used.

+5
source

Write-Output is just an explicit way to send an object that you pass it to the next command in pipleine. Since you are not recording the result, PowerShell uses the default formatting for the object. This is due to the fact that Write-Output does not actually send a string to stdout, it returns an object to the pipeline. The object in the first case is an array of FileSystemInfo objects.

When you return an array to PowerShell without capturing output, PowerShell attempts to iterate over the array and use its default formatting specification to display each object as text on stdout.

So, in the order of the above examples, starting with dir :

  • dir returns System.Array [System.IO.FileSystemInfo]. Since the array is not captured by any code, PowerShell uses its default format for FileSystemInfo to display the contents of the array.

  • the same thing happens as above, but it's you that iterates over. You are actually writing your own array to the pipeline, restoring the same object that get-childitem first. Since, again, no code captures the object of the output array, PowerShell displays it in the same way as in the first case. It is as if you wrote:

     PS C:\temp\testps> $q = Get-ChildItem . "*.txt" PS C:\temp\testps> $children = foreach ($a in $q) {Write-Output $a} PS C:\temp\testps> $children 

    Hope this makes it clear that your example is functionally equivalent to your first example.

  • Here, you convert each object into an array into a string, putting it in quotation marks (which tells PowerShell to call $a.tostring() ) before returning the array of results. So this time you are returning an array of strings to the pipeline. Since you did not capture this array, PowerShell prints to the console its default text output, which in the case of a string is just the text of the string.

  • This is similar to cases 1 and 2 in that PowerShell uses the default output format for the FileSystemInfo object.

  • This does the same as 3, because you are returning an array of strings again. The only difference is semantic ... you call ToString() explicitly, and not implicitly, as when placing an object in quotation marks.

For more information about default formatting, see help about_format

+5
source

All Articles