1

I am using powershell, and have something like

$testResult = vstest.console $myPathToUnitTests.dll

The result comes through fine, but there are new lines (newlines, as in \n ).

I want to use this in my HTML file, and have saved the result as is to a javascript file.

$testResult = vstest.console $myPathToUnitTests.dll
$js = "const result = $($testResult);"
$js | Set-Content $myPathToJsFile

This works fine and I can consume it.

The issue is, it doesn't show the newlines. Within the javascript file I have tried

result = result.replace(/(?:\r\n|\r|\n)/g, '<br />');

Within the powershell I tried

 $testResult = $testResult.replace("\n", "<br />")

However, if I put a breakpoint on testResult in the powershell ID and hover over the variable testResult I see

enter image description here

This means it knows that there are new lines / line breaks. I just don't seem to be able to persist them :(

MyDaftQuestions
  • 4,487
  • 17
  • 63
  • 120
  • 1
    `$testResult = $testResult -replace '\r?\n','
    '`
    – Mathias R. Jessen Feb 09 '18 at 10:05
  • I quess that `$testResult` is not a String but an Array of strings, meaning that you probably need to do: `$TestResult = $TestResult -Join "
    "`
    – iRon Feb 09 '18 at 10:12
  • If it does consider a string: use the systems' `[System.Environment]::NewLine` definition: `$testResult = $testResult -replace [System.Environment]::NewLine, '
    '`
    – iRon Feb 09 '18 at 10:19
  • @iRon it is but is that always the case? Will something like this always return an array or could it return a string/int/enum etc – MyDaftQuestions Feb 09 '18 at 10:29
  • I can't tell *but* if you you put it into an array (`@(...)`), like `$TestResult = @($TestResult) -Join "
    "` it is a **yes**. Important to note here is that if it was already an array it will stay the same array and *not* create another level (this is standard PowerShell behavior).
    – iRon Feb 09 '18 at 11:30
  • Well this works, @iRon so can you move to an answer but if possible, explain how I could have known it was an array/string etc – MyDaftQuestions Feb 09 '18 at 11:40

1 Answers1

2

vstest.console $myPathToUnitTests.dll returns an array not a string therefore you will need to join all the strings (lines) together with the -join operator, like for html:

$TestResult -Join "<br />"

Or if you want to create a multi line text file:

$TestResult -Join [System.Environment]::NewLine

Note: for this, I recommend to use the system's default newline definition ([System.Environment]::NewLine) rather than hardcoded newlines (like: `r`n).

How could you know this?

You can't easily predict what an unknown cmdlet or command returns but the fact that PowerShell is quiet good in dealing with multiple objects (arrays) in a pipeline at once, is a reason to assume that every unknown cmdlet or command could potentially return multiple objects (or strings) collected in an array when assigned to a variable. Needless to say, there are already dozens of similar PowerShell StackOverflow questions like this one that have the same cause. Nevertheless, the related questions itself differ too much to flag them as duplicates. In these other questions, the native PowerShell command Get-Content is probably the most often cause of this PowerShell programming trap.

The best way to find out what is currently returned by the unknown cmdlet is to reveal its type with the GetType() method (which doesn't work on a $Null) or using the PSTypeNames property (which usually returns an array of inherited types):

PS C:\> (get-content .\SingleLine.txt).PSTypeNames
System.String
System.Object

But that doesn't guaranty that it will always return the same (single) object type:

PS C:\> (get-content .\MultipleLines.txt).PSTypeNames
System.Object[]
System.Array
System.Object

The fact that (string) arrays are usually displayed over multiple lines (separated by a newline) directly at the host where they are stocked together (separated by a space) when they are encapsulated in a string could be a trigger to recognize the issue:

PS C:\> $a = "a", "b", "c"
PS C:\> $a
a
b
c
PS C:\> "$a"
a b c
PS C:\>

Will something like this always return an array?

The uncertainty that a cmdlet or command could return an object (string) or an array of objects (strings) raises indeed a new question (as you commented).
This uncertainty is actually easy to resolve in PowerShell; just wrap the output in an array (in parentheses with an @ at the beginning, see also: How can I force Powershell to return an array when a call only returns one object?):

  • If the output was not already an array it will become an array with a single object (string)
  • If the output was already an array it will stay exactly the same array.

In the later condition it is important to understand that no extra levels are added to the resulting array

This technic is commonly used in PowerShell:

$a = "a", "b", "c"
@($a)[0] # still returns: "a"
@(@(@($a)))[0] # or even this returns: "a"
iRon
  • 20,463
  • 10
  • 53
  • 79