2

I want to catch the output exactly as I get it when I run commands in PowerShell.

For instance when I type LS, I get:

enter image description here

Yet when I use this code:

        Runspace runspace = RunspaceFactory.CreateRunspace();
        runspace.Open();

        PowerShell ps = PowerShell.Create(); // Create a new PowerShell instance
        ps.Runspace = runspace; // Add the instance to the runspace
        ps.Commands.AddScript("ls"); // Add a script

        Collection<PSObject> results = ps.Invoke();

        runspace.Close();


        StringBuilder stringBuilder = new StringBuilder();
        foreach (PSObject obj in results)
        {
            Console.WriteLine(obj.ToString());
        }

I get the following output:

Microsoft.Management.Infrastructure.dll
System.Management.Automation.dll
System.Management.Automation.xml
WpfApp1.exe
WpfApp1.exe.config
WpfApp1.pdb

Although this output may come in handy, with an other application I dont get the right output in return, so I would prefer the exact output as I see it in PowerShell itself.

Is there a way to read the output as I get it in PowerShell, line for line?

Michiel Krol
  • 243
  • 3
  • 9

3 Answers3

2

If you want the exact text that powershell produces you then you can use Out-String in the powershell command:

ps.Commands.AddScript("ls | Out-String");

enter image description here


You can also read the values by accessing the Properties of the PSObject:

foreach (PSObject obj in results)
{
    var name = obj.Properties["Name"]?.Value.ToString()
    var mode = obj.Properties["Mode"]?.Value.ToString();
    var length = obj.Properties["Length"]?.Value.ToString();
    var lastMod = (DateTime?)obj.Properties["LastWriteTime"]?.Value;

    Console.WriteLine(string.Format("{0} {1} {2} {3}", mode, lastMod, length, name));
}

Note, as mentioned in mklement0's answer, you don't need to use Runspace to execute this powershell. Consider using Get-ChildItem rather than ls.

haldo
  • 14,512
  • 5
  • 46
  • 52
  • Thank you, with the command `ls` it works, yet when i want the result of selenium-side-runner.exe i don't get the full text that powershell normally shows... – Michiel Krol Mar 22 '20 at 13:43
2

Note: This answer also recommends what part of haldo's helpful answer shows, in a more focused manner and with supplementary information.

Modify your script to pipe your command to the Out-String cmdlet, which uses PowerShell's formatting system to render to a string, the same way that output renders to the console.

ps.AddScript("ls | Out-String"); // Add a script

Note:

  • Windows PowerShell assumes a fixed line width of 120 characters and with (implied) tabular (Format-Table) or wide (Format-Wide) formatting, truncates lines that are longer (except if the output object is of type [string]), with the point of truncation indicated with ...

  • PowerShell [Core] 7+ exhibits the same behavior fundamentally, but only uses default width 120 as a fallback: when the hosting (console-subsystem) executable is running in a console (terminal), the console window's width is used instead, which is the same behavior you get in a regular PowerShell console window (see this answer).

To fix that, pass a large-enough line width to -Width; e.g.:

ps.AddScript("ls | Out-String -Width 200");

Note:

  • In Windows PowerShell, do not use -Width ([int]::MaxValue-1), because every line is then padded to that width, which will result in excessively large output.

  • PowerShell [Core] 7+, this padding is no longer performed, and you can safely use
    -Width ([int]::MaxValue-1)

A few asides:

  • For robustness, I suggest avoiding the use of aliases (such as ls for Get-ChildItem) in scripts and compiled code. In the case at hand, ls wouldn't work on Unix-like platforms, because the alias isn't defined there, so as not to conflict with the platform-native ls utility.

  • It's best to wrap PowerShell ps = PowerShell.Create(); in a using block to ensure that the PowerShell instance is disposed of: using (PowerShell ps = PowerShell.Create()) { ... }

  • There is generally no need to create a runspace explicitly - PowerShell.Create() will create one for you.

  • The System.Management.Automation.PowerShell instance returned by PowerShell.Create() directly exposes methods such as .AddScript() - no need to use the .Commands property.

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

You can get compressed json output from powershell with this command

ls | ConvertTo-Json -Compress

Then deserialize. Also this command provide extra info than see in powershell output.

bduman
  • 9
  • 5