Как получить выходные данные трассировки.NET из задания Powershell?

Я использую компонент.NET в Powershell, который использует Trace.TraceWarning, Trace.TraceInformation и т.п.

Я хочу вывести эти трассировки на консоль при запуске сценария Powershell.

Это работает, когда я использую компонент в текущем сеансе. Например (симуляция эффекта трассировки) выдает вывод "Hello" на консоль:

 $listener = new-object "system.diagnostics.consoletracelistener"
 [System.Diagnostics.Trace]::Listeners.Add($listener) | Out-Null
 [System.Diagnostics.Trace]::TraceInformation("Hello")

Но если я делаю то же самое в задании Powershell, я не получаю вывод, даже если ConsoleTraceListener должен записывать в STDOUT, который, в свою очередь, я ожидал получить от задания. (Что интересно Console.WriteLine с работы тоже не работает - но Write-Host делает).

Я начинаю свою работу так:

$work = {
     $listener = new-object "system.diagnostics.consoletracelistener"
     [System.Diagnostics.Trace]::Listeners.Add($listener) | Out-Null
     [System.Diagnostics.Trace]::TraceInformation("Hello")
}
$job = Start-Job -RunAs32 -ScriptBlock $work
$job | Receive-Job -Wait

2 ответа

Я помню, что столкнулся с чем-то похожим на это несколько лет назад, когда ожидаемые STDOUT и STDIN не работали так, как ожидалось с start-job и exe. Я закончил с использованием System.Diagnostics.Process и перенаправления STDIN и STDOUT. Вот пример, который демонстрирует этот способ, который может помочь вам в том, что вы пытаетесь сделать.

#added extra trace messages with Get-Date and implemented a random delay for demo purpose
$work = {
     $listener = new-object "system.diagnostics.consoletracelistener"
     [System.Diagnostics.Trace]::Listeners.Add($listener) | Out-Null
     1..10 | % {
         Start-Sleep $(Get-Random 5)
         [System.Diagnostics.Trace]::TraceInformation((Get-Date))
    }
}
#Create a process
$process = New-Object System.Diagnostics.Process 
$process.StartInfo.UseShellExecute = $false
#redirect stdout
$process.StartInfo.RedirectStandardOutput = $true
#call powershell
$process.StartInfo.FileName = "powershell.exe"
#pass the $work scriptblock
$process.StartInfo.Arguments = "-noprofile -command $work"
#start the process
$process.Start() | Out-Null
#readlines as they come in and exit when process is done
while(-not $process.HasExited){
    $process.StandardOutput.ReadLine()
}

Выход:

powershell.exe Information: 0 : 01/30/2015 12:27:17
powershell.exe Information: 0 : 01/30/2015 12:27:20
powershell.exe Information: 0 : 01/30/2015 12:27:21
powershell.exe Information: 0 : 01/30/2015 12:27:25
powershell.exe Information: 0 : 01/30/2015 12:27:26
powershell.exe Information: 0 : 01/30/2015 12:27:28
powershell.exe Information: 0 : 01/30/2015 12:27:29
powershell.exe Information: 0 : 01/30/2015 12:27:33
powershell.exe Information: 0 : 01/30/2015 12:27:36
powershell.exe Information: 0 : 01/30/2015 12:27:40

Непонятно, куда вы хотите, чтобы захваченный вывод шел. Большая часть обсуждений до сих пор вращается вокруг консоли, но так как вы назвали ее "работой" (я предполагаю, что вы имеете в виду "запланированное задание"), я не уверен, что консоль - лучшее место. Вы никогда не увидите результаты. Файл журнала звучит гораздо более подходящим. Если это так, вы должны создать TextWriteTraceLister. Это позволит вам установить файл журнала для результатов.

Кроме того, одной из приятных особенностей Tracing в.Net является то, что вы можете подключить более одного слушателя. Поэтому, если вы хотите видеть вывод во время его работы, вы также можете присоединить ConsoleTraceListener, и он не будет мешать записи в файл журнала.

Наконец, также можно написать свой собственный TraceListener. Это полезно для таких вещей, как запись в базу данных журналов или веб-сервис. Чтобы использовать свой собственный TraceListener из PowerShell, вам необходимо собрать слушатель с использованием языка.Net, который можно скомпилировать в сборку библиотеки классов (dll), которую можно развернуть в GAC для использования в вашем проекте.

Другие вопросы по тегам