2015-01-27 19 views
6

Używam NET w PowerShell, który wykorzystuje Trace.TraceWarning, Trace.TraceInformation itpJak przechwycić dane wyjściowe śledzenia .NET z zadania Powershell?

Chcę wyjścia te ślady do konsoli, gdy uruchomię mój skrypt PowerShell.

Działa to, gdy używam komponentu w bieżącej sesji. Na przykład (symulacja efektu śladowe) daje mi moc „cześć” do konsoli:

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

Ale jeśli zrobić to samo w pracy PowerShell dostaję żadnego wyjścia, choć ConsoleTraceListener należy pisać na standardowe wyjście, które z kolei spodziewałem się, że dostanę się do pracy. (Co ciekawe, Console.WriteLine nie działa również z zadaniem - ale robi to Write-Host).

zaczynam moją pracę tak:

$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 
+0

ConsoleTraceListener pisze do konsoli, więc pokrewne: http://serverfault.com/questions/399854/powershell-start-job-output – Caramiriel

+0

ConsoleTraceListener wydaje się napisać do stdout http : //referencesource.microsoft.com/#System/compmod/system/diagnostics/ConsoleTraceListener.cs,b38622e30a1b1559. Ale z jakiegoś powodu przy pracy nie jest on odbierany. – Schneider

+1

Po kilku testach znalazłem kilka ciekawych rzeczy na temat pracy i zadań dla dzieci. Myślę, że ostatecznie problem polega na tym, że powershell nie używa klasy System.Console, ale niestandardową klasę System.Management.Automation.Host.PSHost i przekierowuje strumienie. Wydaje się, że nie jest to zgodne z oczekiwaniami w niektórych przypadkach skrajnych, takich jak Twój. – StephenP

Odpowiedz

0

Nie jest jasne, gdzie chcesz iść do niewoli wyjście. Większość dyskusji do tej pory dotyczy Konsoli, ale ponieważ nazwałaś to "pracą" (zakładam, że masz na myśli Zaplanowane Zadanie), nie jestem pewien, czy Konsola jest najlepszym miejscem. Nigdy nie zobaczysz wyników. Plik dziennika brzmi znacznie lepiej. W takim przypadku należy utworzyć TextWriteTraceLister. Umożliwi to ustawienie pliku dziennika dla wyników.

Dodatkowo jedną z ładnych funkcji Tracing w .Net jest możliwość dołączenia więcej niż jednego słuchacza. Jeśli więc chcesz zobaczyć dane wyjściowe podczas ich działania, możesz także dołączyć ConsoleTraceListener i nie będzie to kolidowało z zapisywaniem do pliku dziennika.

Wreszcie, istnieje również możliwość napisania własnego TraceListener. Jest to przydatne w takich sytuacjach, jak zapisywanie do bazy danych logowania lub usługi internetowej. Aby użyć własnego TraceListener z PowerShell, musisz zbudować detektor przy użyciu języka .Net, który może być skompilowany w bibliotekę klasy (dll), która może zostać wdrożona w GAC do użycia w twoim projekcie.

+0

Jest to zadanie typu powershell, jak w przypadku czegoś, co zaczyna się od Start-Job. Powodem, dla którego używam zadania btw, jest to, że potrzebuję załadować i używać zestawu x86 .NET z 64-bitowej powłoki. Job zapewnia łatwy i łatwy sposób na wykonanie tego zadania. – Schneider

+0

Instrukcje śledzenia, działające w zwykłej sesji psh, pobierają dane wyjściowe do potoku.Najlepiej byłoby, gdyby zostały zwrócone z polecenia receive-job w taki sam sposób, jak normalne wyniki wyjściowe. – Schneider

+0

Pomocne może okazać się: http://stackoverflow.com/questions/11973775/powershell-get-output-from-receive-job –

0

Pamiętam, że wpadłem na coś podobnego do tego z lat temu, kiedy oczekiwane STDOUT i STDIN nie zachowywały się zgodnie z oczekiwaniami przy starcie i exe. Skończyło się na użyciu System.Diagnostics.Process i przekierowanie STDIN i STDOUT. Oto przykład, który pokazuje to obejście w sposób, który może pomóc ci w tym, co próbujesz zrobić.

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

wyjściowa:

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 
+0

Dziękuję za odpowiedź, ale uważam, że proces początkowy to "oszustwo";). Próbuję zrozumieć, dlaczego to nie działa na rzecz pracy – Schneider

Powiązane problemy