1

This works perfectly on Windows 10 using powershell but fails badly on Win Server 2012 R2. I have tried many forms using redirect and -outfile but at best end-up with an empty file or broken script.

Can any one help me send the one liner below to a txt file on win server 2012 R2, I'm just not getting it

$((Get-WmiObject -Query "select Name, PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor") | foreach-object { write-host "$($_.Name)    :    $($_.PercentProcessorTime)"}) *>&1 > output.txt
Jonathon Anderson
  • 1,162
  • 1
  • 8
  • 24
  • 1
    As an aside: The CIM cmdlets (e.g., `Get-CimInstance`) superseded the WMI cmdlets (e.g., `Get-WmiObject`) in PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell [Core] (version 6 and above), where all future effort will go, doesn't even _have_ them anymore. For more information, see [this answer](https://stackoverflow.com/a/54508009/45375). – mklement0 Jul 01 '20 at 21:12

2 Answers2

1

Write-Host, as the name implies, writes to the host, which in a console window is that window's display (screen), bypassing PowerShell's (success) output stream, the latter being what the pipeline operator (|) and the redirection operator > operate on.

In PowerShell v5+ only, Write-Host writes to the information output stream (stream number 6 - see the about_Redirection help topic; by default, that output still goes to the host) and can therefore be redirected - either via 6> or via *> - so the catch-all redirection *>&1, which redirects all streams to the success output stream (1), can indeed be used to redirect Write-Host to the success output stream, but not in earlier PowerShell versions - and Windows Server 2012 R2 shipped with PowerShell version 4.

However, in your case there is no good reason to use Write-Host to begin with: either use Write-Output - the cmdlet whose purpose is to write to the success output stream (1) - or, preferably, use PowerShell's implicit output feature, where any output (return value) not captured in a variable, piped or redirected is implicitly written to the success output stream:

# Note how the use of "$($_.Name)    :    $($_.PercentProcessorTime)"
# *by itself* implicitly causes it to be *output* (written to the pipeline).
Get-WmiObject -Query "select Name, PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor" |
  Foreach-Object { "$($_.Name)    :    $($_.PercentProcessorTime)" } > output.txt

Note the absence of $(...), the subexpression operator in the command, which isn't needed.

If the specific spacing between the columns isn't important, you can more simply write (since only 2 properties are being select, implicit Format-Table formatting is applied):

Get-WmiObject -Query "select Name, PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor" |
  Select-Object Name, PercentProcessorTime > output.txt

Note: The CIM cmdlets (e.g., Get-CimInstance) superseded the WMI cmdlets (e.g., Get-WmiObject) in PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell [Core] (version 6 and above), where all future effort will go, doesn't even have them anymore. For more information, see this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

Try this... note that it is appending to the file, so if you run it twice, you will have two runs' worth of data

$((Get-WmiObject -Query "select Name, PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor") | foreach-object { "$($_.Name)    :    $($_.PercentProcessorTime)" >> output.txt}) 


EDIT

OP accepted this as the answer, but it's not necessarily the best solution. For a thorough explanation and another solution, I recommend a different answer submitted for this question.

Jonathon Anderson
  • 1,162
  • 1
  • 8
  • 24
  • Jonathon: the `>>` is a distraction; just use `>`; the `$(...)` is unnecessary (while it is present in the OP, it's not worth reusing, unless the redundancy is pointed out). Most importantly: it is switching from using `Write-Host` to _implicit_ output of the string to the _success output stream_ that makes your solution work (in PS versions _before_ version 5). Explaining this aspect in your answer is crucial to making it helpful to future readers. – mklement0 Jul 01 '20 at 22:09
  • @mklement0 I tested with the single `>` operator, but it overwrites the file with every iteration of the `Foreach-Object` loop, so the final output only has one line. I tend not to comment on potentially stylistic coding like using `$(...) ` – Jonathon Anderson Jul 01 '20 at 22:40
  • That's because you put the `>>` _inside_ the `foreach-object` script block - put it _after_ (e.g, `1..10 | ForEach-Object { "[$_]" } > foo.txt`) - that's also much more efficient. – mklement0 Jul 01 '20 at 22:47
  • The use of `$(...)`, generally speaking, is _not_ just a matter of _style_: it can fundamentally alter the behavior of the command (up-front collection _in full, in memory_ vs. memory-throttling _streaming_ behavior). – mklement0 Jul 01 '20 at 22:51
  • Comments on `$(...)` aside: my main point was that the switch from `Write-Host` to implicit output is what needs explaining in your answer for it to be useful. – mklement0 Jul 01 '20 at 22:52
  • 1
    @mklement0 All good points. Thanks for the feedback – Jonathon Anderson Jul 01 '20 at 23:33
  • @mklement do you have any additional information on use of sub-expressions `$(...)` within expanding strings? eg mem consequences and/or comparison to other techniques. To keep this clean I can delete this comment after the fact. Thanks in advance! – Steven Jul 01 '20 at 23:38
  • 1
    @Idaho_Huskey I would accept mklement0's answer. It's more explanatory and the code is actually more efficient. – Jonathon Anderson Jul 01 '20 at 23:59
  • Jonathon, while all the answers did work on the win2012 r2 server, from a windows server perspective, the devil is in the details... The file is transferred to a Unix server were a reports is compiled. There were file format issues with all but the append solution (>>). in the other two solutions the data appeared in one long line or each character was on a new line after the transfer regardless of the method of transfer ftp, sftp or using a samba drive map. For that reason I went with the >> approach. – Idaho_Huskey Jul 02 '20 at 01:36
  • @Idaho_Huskey: All file operations in Windows PowerShell (and PowerShell [Core] _on Windows_) will result in Windows-style CRLF rather than Unix-style LF-only newlines, irrespective of whether you use `>>` or `>`. The `>`-based solution in my answer neither results in a single long line, nor does it result in each character on its own line - in any PowerShell version since v2. If it does for you, you didn't copy the command correctly. – mklement0 Jul 02 '20 at 01:48
  • @Steven: See https://stackoverflow.com/a/54794690/45375 – mklement0 Jul 02 '20 at 02:19