Как перехватить полный текст вызова из класса powershell в C# - PullRequest
1 голос
/ 22 марта 2020

Я хочу получать выходные данные в точности так, как получаю при запуске команд в PowerShell.

Например, когда я набираю LS, я получаю:

enter image description here

Тем не менее, когда я использую этот код:

        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());
        }

я получаю следующий вывод:

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

Хотя этот вывод может пригодиться, с другим Приложение Я не получаю правильный вывод взамен, поэтому я предпочел бы точный вывод, как я вижу его в самой PowerShell.

Есть ли способ прочитать вывод, как я получаю его в PowerShell, строка за строкой?

Ответы [ 3 ]

2 голосов
/ 22 марта 2020

Если вам нужен точный текст, который выдает PowerShell, вы можете использовать Out-String в команде powershell:

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

enter image description here


Вы также можете прочитать значения, открыв Properties из 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));
}

Примечание , как указано в mklement0 ответ, вам не нужно использовать Runspace для выполнения этого PowerShell. Попробуйте использовать Get-ChildItem вместо ls.

2 голосов
/ 22 марта 2020

Примечание. В этом ответе также рекомендуется, какая часть полезного ответа Халдо показывает, более сфокусированным образом и с дополнительной информацией.

Измените сценарий на конвейер ваша команда для командлета Out-String, который использует систему форматирования PowerShell для рендеринга в строку так же, как вывод выводится на консоль.

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

Обратите внимание, что Windows PowerShell предполагает фиксированную ширину строки 120 символов и усекает строки, которые длиннее (за исключением случая, когда выходной объект имеет тип [string]), с точкой усечения, обозначенной как ....

Чтобы исправить это, передайте достаточно большую ширину линии в -Width; Например:

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

Примечание: не используйте -Width ([int]::MaxValue), потому что каждая строка затем дополняется до этой ширины , что приведет к чрезмерно большому выводу.

PowerShell [Core] 6.1 + , к счастью, больше не выполняет усечение по умолчанию (а также не дополняет), но вы можете запросить его с помощью -Width.

Несколько замечаний:

  • Для надежности я предлагаю избегать использования псевдонимов (таких как ls для Get-ChildItem) в скриптах и ​​скомпилированном коде. В данном случае ls не будет работать на Unix -подобных платформах, потому что псевдоним там не определен, чтобы не конфликтовать с нативной платформой ls.

  • Лучше всего обернуть PowerShell ps = PowerShell.Create(); в блок using, чтобы обеспечить удаление экземпляра PowerShell: using (PowerShell ps = PowerShell.Create()) { ... }

  • Обычно в этом нет необходимости чтобы создать пространство выполнения явно - PowerShell.Create() создаст его для вас.

  • Экземпляр System.Management.Automation.PowerShell, возвращаемый PowerShell.Create(), напрямую предоставляет такие методы, как .AddScript() - не нужно использовать свойство .Commands.

0 голосов
/ 22 марта 2020

Вы можете получить сжатый json вывод из powershell с помощью этой команды

ls | ConvertTo-Json -Compress

Затем десериализовать. Кроме того, эта команда предоставляет дополнительную информацию, чем в выводе powershell.

...