Ищите, как писать подробные или отладочные строковые сообщения в пространство выполнения PowerShell без определения командлета C # - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть библиотека классов C #, которая предоставляет ряд интерфейсов, которые можно вызывать из сценариев PowerShell (.PS1) и расширенных модулей (.PSM1).У меня есть статический метод для записи подробных и отладочных сообщений на консоль с использованием класса System.Console:

public class Write
{

        public static void Verbose(string msg, string source)
        {

            if (Config.EnableVerbose)
            {

                ConsoleColor originalForeGroundColor = Console.ForegroundColor;
                ConsoleColor originalBackGroundColor = Console.BackgroundColor;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.BackgroundColor = ConsoleColor.Black;
                Console.Write("VERBOSE: {0} {1}{2}", source, msg, Environment.NewLine);
                Console.ForegroundColor = originalForeGroundColor;
                Console.BackgroundColor = originalBackGroundColor;

            }

       }

}

Однако, когда эти сообщения отображаются в консоли PowerShell, их невозможно перехватить с помощью перенаправления, напримерс Out-File, >&0 или даже с Start-Transcript.

Я прочитал about_Redirection, и использование модификаторов перенаправления не захватывает вывод консоли.Например, используя расширенную функцию PowerShell (он же Cmdlet), я написал:

Get-CommandTrace -ScriptBlock { Get-Resource } *> C:\Temp\capture.log

Командлет Get-CommandTrace устанавливает $VerbosePreference = 'Continue' во время выполнения ScriptBlock и захватываетподробный вывод Get-Resource.Но не захватывает вывод консоли из моей библиотеки C #.

Итак, мой вопрос прост: может ли класс C #, который не является ни классом Cmdlet, ни унаследованным классом, иметь возможность записывать выходные данные в существующее пространство выполнения PowerShellэто вызывается из?

Ответы [ 2 ]

0 голосов
/ 31 июля 2019

Хотя приведенный выше ответ от mklement0 является хорошим, он не будет работать, если вы попытаетесь использовать его с PowerShellCore или нацеливаться на .NetStandard 2.0, поскольку API CreateNestedPipeline устарел.(См. этот поток в репозитории PowerShellStandard GitHub.)

Итак, вместо этого у меня есть этот рабочий код:

Add-Type -TypeDefinition @'
using System.Management.Automation;
using System.Management.Automation.Runspaces;

    public class Write
    {

        public static void Verbose(string msg)
        {

            using (PowerShell initialPowerShell = PowerShell.Create(RunspaceMode.CurrentRunspace))
            {

                initialPowerShell.Commands.AddScript("Write-Verbose " + msg.Replace("\"", "\"\"") + "\" -v");
                initialPowerShell.Invoke();

            }

        }

    }
'@

$VerbosePreference = 'Continue'

# Regular output to the verbose stream.
Write-Verbose 'msg1'

# Verbose output via the custom type.
# !! This can NOT be redirected from the outside.
[Write]::Verbose('msg2')

# !! SUPPRESSING or REDIRECTING TO A FILE only works
# !! when DIRECTLY APPLIED to the method call.
[Write]::Verbose('msg3') 4> $null
[Write]::Verbose('msg4') 4> t.txt

# !! REDIRECTING TO THE STANDARD OUTPUT STREAM (1) for the OUTSIDE works,
# !! but obviously it then merges with success output.
[Write]::Verbose('msg5') 4>&1

# !! To REDIRECT TO THE STANDARD OUTPUT STREAM (1) and capture the result
# !! INSIDE your script, invoke the method call in  (...) or $(...) or @(...)
$out = ([Write]::Verbose('msg6') 4>&1)
"[$out]"

, который работает с PowerShell 5.1 для Windows,PowerShell Core 6.2.2 для Windows и Linux (Ubuntu / Debian).

Я все равно оставлю ответ mklement0 отмеченным как ответ на исходный вопрос.Я просто добавляю еще одно, основанное на исследованиях, которые я собрал за последние несколько дней по переносу моей библиотеки классов на .NetStandard 2.0.

0 голосов
/ 28 февраля 2019

Примечание:

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

Задача состоит в том, чтобы записать в вызывающий конвейер выходных потоков (как вы заметили, записывая через Consoleне связан с потоками вывода PowerShell и печатает непосредственно на консоль).

Хотя мне удалось получить ссылку на вызывающую область выполнения , я не мог понять, как ее получить, чтобы работающий конвейер , так что лучшее, что я мог придумать, это создать вложенный конвейер, который частично работает, с ограничением, обсужденным в комментарияхследующий код:

Add-Type -TypeDefinition @'
  using System.Management.Automation;
  using System.Management.Automation.Runspaces;

  public class Write
  {

      public static void Verbose(string msg)
      {
        // Create a nested pipeline in the current runspace and
        // call Write-Verbose in it.
        var rs = Runspace.DefaultRunspace
                  .CreateNestedPipeline("Write-Verbose \"" + msg.Replace("\"", "\"\"") + "\"", false)
                  .Invoke();
      }

  }
'@

$VerbosePreference = 'Continue'

# Regular output to the verbose stream.
Write-Verbose 'msg1'

# Verbose output via the custom type.
# !! This can NOT be redirected from the outside.
[Write]::Verbose('msg2')

# !! SUPPRESSING or REDIRECTING TO A FILE only works
# !! when DIRECTLY APPLIED to the method call.
[Write]::Verbose('msg3') 4> $null
[Write]::Verbose('msg4') 4> t.txt

# !! REDIRECTING TO THE STANDARD OUTPUT STREAM (1) for the OUTSIDE works,
# !! but obviously it then merges with success output.
[Write]::Verbose('msg5') 4>&1

# !! To REDIRECT TO THE STANDARD OUTPUT STREAM (1) and capture the result
# !! INSIDE your script, invoke the method call in  (...) or $(...) or @(...)
$out = ([Write]::Verbose('msg6') 4>&1)
"[$out]"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...