2009-10-09 10 views
8

Yerel win32 API'sini kullanarak bir Windows uygulaması yazdım. Uygulamam diğer işlemleri başlatacak ve çıkışı yakalayacak ve stderr çıktısını kırmızıyla vurgulayacaktır. Bunu gerçekleştirmek için,Stdout/stderr'i ayrı olarak yakalayabilir ve asıl düzeni koruyabilir miyim?

I stdout ve standart hataya için ayrı bir boru yaratmak ve CreateProcess çağrı zaman STARTUPINFO yapısında kullanın. Sonra, her bir stdout/stderr tutamacı için borudan okuyan ve çıktıyı bir pencereye kaydeden ayrı bir iş parçacığı başlatırım. Bu, çoğu durumda iyi çalışır. Sorun şu ki, alt işlem hızlı bir şekilde stderr ve stdout için günlüğe kaydediyorsa, uygulamanız bazen çıkışı yanlış sırayla gösterecektir. Bunun, her tanıtıcıdan okumak için iki iş parçacığı kullanmasından kaynaklandığını farz ediyorum.

o ikisi arasında ayrım yapmak mümkün olurken, onlar için yazılmış orijinal sırayla stdout ve stderr'yi yakalamak mümkün mü?

cevap

3

oldukça, bu yapılamaz emin paketler halinde yazmak ve her birine bir zaman damgası eklemek için kökenli program yazarken eksiğim var. Bu olmadan, normalde, çocuk işleminin standart kitaplığındaki arabelleğe almayı planlayabilirsiniz, bu nedenle, hatta üstünden boruya iletildikleri zaman bile, zaten sıra dışı olma şansı çok yüksektir.

+0

Evet, bu yaklaşımdır ama olarak çok fazla aşağı oy açık forumlarda bunu çalışmakla kaçınılmaz sonucudur op söyleyecek kadar cesur değildi. –

+0

Bu nasıl olabilir? CMD.exe her zaman doğru nasıl görünüyor? yapıldığını ancak CAN gibi – paulm

+0

görünüyor onun için yazıldığı akışı bilmek mümkün değildir: http://stackoverflow.com/questions/18529662/capture-process-stdout-and-stderr-in-the-correct-ordering – paulm

0

Gerçekten öyle düşünmüyorsunuz, ama std_out sistem tasarımcılarının kontrolündedir - std_out'un tam olarak nasıl ve ne zaman yazılacağı, programımın belgelendirilmiş olmayan konulara tabi kılındığı sistem zamanlayıcıya tabidir.

Bir gün bir şeyler yazıyordum ve editörde kod açıkken sistemdeki aygıtlardan birinde biraz çalıştım ve sistemin sürücüye gerçek zamanlı önceliği verdiğini fark ettim. özel kod, özel kod olarak önemli bir onda biri kadar bir yerde.

Yeniden tersini sen yazma sıralı sipariş almak böylece olacak az söylemek zor olması olduğunu.

0

Sen Stdout'a stderr'yi yönlendirebilirsiniz:

command_name 2>&1

Bu Hatırladığım kadarıyla, borular kullanılarak C mümkündür.

GÜNCELLEME: Oh, üzgünüm - ikisi arasında ayırt etmek mümkün olmakla ilgili bölümünü kaçırdım. Ben TextMate bir şekilde kullanıcı görünür kodu kullanarak bir şekilde yaptı biliyorum ... Bir süredir bakmadı, ama ben bir göz vereceğim. Fakat biraz daha düşündükten sonra, Ruby'de Open3 gibi bir şey kullanabilir miydiniz? Aynı anda hem STDOUT hem de STDERR'u izlemeniz gerekecek, ancak gerçekten hiç kimse bu ikisine ilişkin belirli bir çıkış sırasını beklememelidir.

GÜNCELLEME 2: Ben Ruby de ne anlama geldiğini örneği:

require 'open3' 

Open3.popen3('ruby print3.rb') do |stdin, stdout, stderr| 
    loop do 
    puts stdout.gets 
    puts stderr.gets 
    end 
end 

... print3.rb sadece burada:

loop do 
    $stdout.puts 'hello from stdout' 
    $stderr.puts 'hello from stderr' 
end 

yerine düz puts çıktı atma, bir gönderebilir programınızda yazdıracağınız bir gözlemciye mesaj. Üzgünüz, bu makinede Windows yok (ya da hemen kullanılabilir), ama umarım bu kavramı gösterir.

0

'u birbirinden ayırmasanız dahi, doğru sırada birbirlerini değiştireceklerinin garantisi yoktur. Gördüğüm stdout ve stderr çoğu uygulamalarda

2

, stdout'u tamponlu ve stderr değildir. Temel olarak bunun anlamı, programı düz komut satırında çalıştırırken bile sıraya gireceklerinin garanti edilmemesidir.

http://en.wikipedia.org/wiki/Stderr#Standard_error_.28stderr.29

Kısa cevap: Sen onlar cmd.exe görünen sıralaması garanti edilmez çünkü onlar cmd.exe görünen sırayla satırları okumak sağlamak mümkün değil. niyet çıkış os mevcut programı açıklama olduğu için

0

, iki akımın herhangi bir muhtemel serpiştirme doğru olmalıdır. Orijinal geliştirici, zorunlu siparişin onurlandırıldığından emin olmak için uygun flush() çağrılarını yerleştirmiş olacaktır. Daha önce açıklandığı gibi

, bir zaman damgası ile yazılır, her fragman kayıt ve aslında çıkış aygıtları tarafından görülen dizisini geri kazanmak için kullanabilir.

İlgili konular