Soru İşlem çalışıyor olsa da Process.HasExited true değerini döndürüyor?


Bunu gözlemliyorum Process.HasExited bazen döner true süreç hala çalışıyor olsa bile.

Aşağıdaki kodum "testprogram.exe" adı verilen bir işlemi başlatır ve ardından çıkmasını bekler. Sorun şu ki bazen istisna atılıyor; öyle görünüyor ki HasExited döner true Sürecin kendisi sistemde hala canlı - bu nasıl olabilir?

Programım, sonlanmadan hemen önce bir günlük dosyasına yazıyor ve bu yüzden, bu günlük dosyasının okunmadan önce (yani işlemin sonlandırıldığı / sonlandırıldığı) kesinlikle emin olmalıyım. Varlığını kontrol etmek sürekli bir seçenek değildir.

// Create new process object
process = new Process();

// Setup event handlers
process.EnableRaisingEvents = true;
process.OutputDataReceived += OutputDataReceivedEvent;
process.ErrorDataReceived += ErrorDataReceivedEvent;
process.Exited += ProgramExitedEvent;

// Setup start info
ProcessStartInfo psi = new ProcessStartInfo
                           {
                               FileName = ExePath,
                               // Must be false to redirect IO
                               UseShellExecute = false,
                               RedirectStandardOutput = true,
                               RedirectStandardError = true,
                               Arguments = arguments
                           };

process.StartInfo = psi;

// Start the program
process.Start();

while (!process.HasExited)
    Thread.Sleep( 500 );

Process[] p = Process.GetProcessesByName( "testprogram" );

if ( p.Length != 0 )
    throw new Exception("Oh oh");

GÜNCELLEME: Sadece beklemeyi denedim process.WaitForExit() Yoklama döngüsü yerine ve sonuç tam olarak aynıdır.

Ekleme: Yukarıdaki kod sadece benzer bir 'sorun' ortaya koymaktı. Açıklığa kavuşturmak için; Benim problemim hala sürecin bir kısmını elde edemem. Process.GetProcessesByName( "testprogram" ); ayarlandıktan sonra HasExited doğru

Asıl sorun, harici olarak çalıştırdığım programın bir dosya yazmasıdır - daha önce sona erer (incelikle). kullanırım HasExited sürecin ne zaman bitip bitmediğini kontrol etmek için dosyayı okuyabildiğimden (işlem çıktığı için!), ama öyle görünüyor ki HasExited döner true bazen program henüz dosyayı diske yazmamışsa bile. İşte tam sorunu gösteren örnek kod:

// Start the program
process.Start();

while (!process.HasExited)
    Thread.Sleep( 500 );
// Could also be process.WaitForExit(), makes no difference to the result

// Now the process has quit, I can read the file it has exported
if ( !File.Exists( xmlFile ) )
{
    // But this exception is thrown occasionally, why?
    throw new Exception("xml file not found");
}

28
2018-03-25 21:52


Menşei


Testprogram.exe nasıl çıkıyor? Üzerinde Kill () mi çağırıyorsunuz, yoksa erken mi bitiyor? Tüm yazılarını bitirdikten sonra normal mi çıkıyor? - Tanzelax
Bilmiyorum. Çalıştığım harici bir program ve bunun için kaynak kodum yok. Tek bildiğim, bir dosya (sonuçlarının dışa aktarılması) kapanmadan hemen önce kapanmasıdır, çünkü gözlemlediğim davranış budur. Dönüş değeri 0'dır, bu yüzden normal olarak çıktığını tahmin ediyorum. Aksi halde hiçbir şey gösterilmedi. - johnrl
@johnrl bu sorunu çözdünüz mü hiç kodunuzu paylaşabilirsiniz - GowthamanSS
Sonuçta çıktısını aldığınız xml dosyası ise, bir FileSystemWatcher'ı düşündünüz mü? msdn.microsoft.com/en-us/library/... - Fred
@johnrl Her şeyin siz gittiğini düşündüğünüz gibi gidip gitmediğini merak ediyorum ... Bunun gibi süreçleri yönetmek konusunda hiç sorun yaşamadım. Belki bir çocuk süreç başlatır ve ana neden, ya da herhangi bir nedenden dolayı pid değişiklikleri, ya da Windows hata raporlama çalışır gibi başka bir süreçte damping yapılır ya da ... sadece çok fazla değişken var. Procmon'u (sysinternals), hangi işlemin ne işe yaradığını ve pid'in süreç kaşifinde olup olmadığını (sysinternals'dan procexp) lütfen öğrenmek için kullanabilir misiniz? - atlaste


Cevaplar:


Bunun eski bir yayın olduğunu anlıyorum, ancak uygulamanızın uygulamadan önce neden Exited olayını çalıştırdığını öğrenmek için arayışımda, gelecekte bu sorunu yaşayan insanlara yararlı olabileceğimi düşündüğüm bir şey öğrendim.

Bir işlem başlatıldığında, bir PID atanır. Kullanıcıya Kullanıcı Hesabı Denetimi iletişim kutusu girilir ve 'Evet' seçilirse, işlem yeniden başlatılır ve yeni bir PID atanır.

Bununla birkaç saatliğine oturdum, umarım bu zamandan tasarruf edebilir.


11
2017-10-22 13:11





Bu şekilde denemenizi öneririm:

process.Start();

while (!process.HasExited)
{
    // Discard cached information about the process.
    process.Refresh();

    // Just a little check!
    Console.WriteLine("Physical Memory Usage: " + process.WorkingSet64.ToString());

    Thread.Sleep(500);
}

foreach (Process current in Process.GetProcessesByName("testprogram"))
{
    if ((current.Id == process.Id) && !current.HasExited)
        throw new Exception("Oh oh!");
}

Her neyse ... HasExited'in MSDN sayfasında şu aşağıdaki vurgulanmış notayı okuyorum:

Standart çıktı eşzamansız olaya yönlendirildiğinde   işleyicileri, çıkış işleminin mümkün olmaması mümkündür   Bu özellik doğru olduğunda tamamlandı. Asenkronize olduğundan emin olmak için   Olay işleme tamamlandı, WaitForExit () aşırı yüklemesini çağırın.   Bu HasExited kontrol etmeden önce hiçbir parametre alır.

Herşeyi yeniden yönlendirirken probleminizle bağlantılı olabilir.


6
2018-01-15 15:52





İlki, test programının kendiliğinden bir süreç oluşturup, bu işlemin bitmesini beklemeden çıkıp çıkmadığından emin misiniz?? Burada bir tür yarış durumuyla uğraşıyoruz ve test programı önemli olabilir.

Bunu yapmak istediğim ikinci nokta - "Bu log dosyasının var olduğundan kesinlikle emin olmalıyım". Eh, böyle bir şey yok. Çekini yapabilirsin, sonra dosya gitti. Bunu ele almanın ortak yolu, kontrol etmek değil, dosya ile ne yapmak istediğinizi yapmaktır. Devam edin, okuyun, istisnaları yakalayın, şey kararsız görünüyorsa ve bir şeyi değiştirmek istemiyorsanız tekrar deneyin. Eğer sistemde birden fazla aktörünüz varsa (iş parçacığı ya da her neyse) işlevsel check-and-do çalışmaz.

Bir grup rastgele fikir takip ediyor.

FileSystemWatcher'ı kullanmayı denediniz mi ve işlemin tamamlanmasına bağlı değil misiniz?

Dosyayı okumayı denediğinizde daha iyi olur mu (var olup olmadığını kontrol etme, oyunculuk Bunun yerine) süreç içinde. [yapmamalı]

Sistem sağlıklı mı? Etkinlik Günlüğünde şüpheli bir şey var mı?

Gerçekten agresif antivirüs politikası olabilir mi?

(Tüm kodu görmeden ve test programına bakmadan çok şey söyleyemem.)


4
2018-01-17 21:46





Biliyorum, bu eski bir yazı ama belki birine yardım edebilirim.
Süreç sınıfı beklenmedik şekilde davranabilir! HasExited Süreç çıkmışsa doğru döner veya İşlem yönetici ayrıcalıklarıyla çalışırsa ve programınız yalnızca kullanıcı ayrıcalıkları.


4
2018-01-04 20:56





Yani sadece sorunun kök nedenine ilişkin daha fazla araştırma için belki de gerçekten neyin olup bittiğini kontrol etmelisiniz. Proses Monitörü. Basitçe başlatın ve harici programı ve kendi aracınızı dahil edin ve ne olduğunu kaydetmesine izin verin.

Günlük içerisinde harici aracın çıktı dosyasına nasıl yazdığını ve bu dosyayı nasıl açtığınızı görmelisiniz. Fakat bu kayıt içerisinde tüm bu erişimlerin hangi sırada gerçekleştiğini görmelisiniz.

Aklıma gelen ilk şey, Process sınıf yalan söylemez ve süreç söylendiği zaman gerçekten gider. Yani sorun şu ki, bu noktada dosya hala tam olarak mevcut değil gibi görünüyor. Bence bu bir işletim sistemi problemiDosyanın bazı bölümlerini disk üzerinde tam olarak yazılmayan bir önbellek içinde tutmasına neden olur ve araç, dosya tutamaçlarını temizlemeden kolayca çıkarılır.

Bunu göz önünde bulundurarak, harici aracın dosyayı oluşturduğu, çıktığı ve dosyanın temizleneceğini / kapatılacağını (işletim sistemi tarafından [bu noktayı günlük içinde bulduğunuzda filtreleri kaldırabilirsiniz]) görmeniz gerekir.

Eğer varsayımlarım doğruysa, temel neden dışsal aracınızın kötü davranışıdır ki, bu da değişemediğinden, süreç çıktıktan sonra biraz bekleyiniz ve zaman aşımının dosya akışı için yeterince uzun olmasını umuyoruz. İşletim sistemi tarafından kapatılmış (belki de dosyayı bir döngü içinde zaman aşımına sahip olana kadar açmaya çalışın).


3
2018-01-16 12:36





Bir başlangıç ​​için, onu yoklamaktan ziyade Process.WaitForExit kullanarak bir sorun mu var?

Her halükarda, işlemin kullanılabilir bir bakış açısından çıkması teknik olarak mümkün olmakla birlikte, disk floş yıkaması gibi şeyler yapılırken, işlem hala kısa bir süre içindedir. Günlük dosyası özellikle büyük (veya disk üzerinde ağır bir performans sergiliyor mu)?


1
2018-03-25 21:56



Toplam mutlak maksimum boyutlar 1mb civarındadır. Yoklama kullanmamın nedeni, bekletme görevini herhangi bir zamanda iptal edebilmem ve WaitForExit ile en azından zaman aşımına kadar engellenmiş olmam. Sizce, HasExited'in gerçek geri dönüşüne rağmen programın diske akıtarak temizlenmesi mümkün olabilir mi? HasExited'in doğru olduğu süreç sürecinin tamamen ölü / gitmediğini garip buluyorum. Belgede anlatabildiğim kadar özel bir durum söz konusu değil. - johnrl
Daha önce gördüğüm bir şey ama küçük boyutlarda değil. Başka bir yorumcu tarafından belirtildiği gibi, Süreç sınıfı işlem için bir referans sürdürecek olsa da, Çıkış için kontrol ettikten sonra ancak işlem listesinde bulmaya başlamadan önce İşlem örneğinde At'ı çağırmak isteyebilirsiniz. - tyranid


İki olasılık var, süreç nesnesi sürece bir referans tutmaya devam ediyor, bu yüzden çıktı, ancak henüz silinmedi. Veya çalışan işlemin ikinci bir örneğiniz var. Ayrıca emin olmak için işlem kimliğini de karşılaştırmalısınız. Bunu dene.

    ....

    // Start the program
    process.Start();


    while (!process.HasExited)
        Thread.Sleep( 500 );

    Process[] p = Process.GetProcessesByName( "testprogram" );
    if ( p.Length != 0 && p[0].Id == process.id && ! p[0].HasExited)
        throw new Exception("Oh oh");

1
2018-03-25 21:59



Sadece tek bir örneğim var ve I. Windows Görev Yöneticisi'ni açık tutmaya ve işlem listesini izlemeyi denedim (aynı zamanda kimlikleri kontrol ediyorlar, eşleşiyorlar) ve gerçekten kodum istisnayı atarken işlem hala listede. Bazen istisna atıldığında neredeyse anında çıkar, diğer zamanlarda ortadan kaybolması bir veya iki saniye sürebilir. Görev Yöneticisi güvenilebilir (belki gecikme?) Emin değilim, ancak gerçek benim kodum istisna atar - her seferinde değil ama yaklaşık 1/10 çalışır. - johnrl
Process.HasExited bir kez doğru, o zaman süreç vardır çıkıldı. Öldü. Özellikle işlem nesnesine açık tutamaçlar varsa, belirli bir süre için bir zombi olabilir. GetProcessByName () yönteminin bazen bu işlemi döndürmesi, işlemin hala bir zombi olduğu dışında bir anlam ifade etmemesidir. Malısın process.Dispose() Sapın serbest bırakıldığından emin olmak için. Ama GetProcessByName kullanarak "test" yapmak sadece yapmak için makul bir şey değildir. process.HasExited yapabileceğiniz tek güvenilir testtir ve bunu zaten yaptınız. - John Knoeller
Makul geliyor. Ama anlamıyorum ki, 'testprogram' yazıyor (ki kapanmadan hemen önce geliyor), HasExited doğru olduğunda diske yazılmıyor. Süreç bir zombi ise bu nasıl olabilir (o zaman her şeyi diske temizlemeliydi, değil mi?). Proses nesnesini atmak, bildiğim kadarıyla işlem tarafından yürütülen program üzerinde hiçbir etkiye sahip değildir, bu nasıl yardımcı olur? - johnrl


Göre MSDN belgeleri için HasExited.

Bir tanıtıcı işleme açıksa,   işletim sistemi   süreç olduğunda işlem belleği   çıktı, ancak yönetimini koruyor   gibi işlem hakkında bilgi   tutamaç, çıkış kodu ve çıkış zamanı.

Muhtemelen ilgili değil, ama dikkati çekiyor.

Eğer sadece 1 / 10'luk bir problemse ve süreç bir saniye sonra kaybolursa, HasExited'in kullanımına bağlı olarak, HasExited kontrol çalışmasından sonra başka bir gecikme eklemeyi deneyin.

while (!process.HasExited)
    DoStuff();
Thread.Sleep(500);
Cleanup();

ve sorunun devam edip etmediğine bakın.

Şahsen ben her zaman kullandım Exited herhangi bir yoklama yerine olay işleyicisi ve etrafındaki basit bir özel sarmalayıcı System.Diagnostics.Process iş parçacığı güvenliği gibi şeyleri işlemek için CloseMainWindow() bunu takiben WaitForExit(timeout) ve sonunda Kill(), günlüğe kaydetme, ve bir sorunla karşılaşmadılar.


1
2018-03-25 22:34





Belki sorun test programındadır? Bu kod güzel bir şekilde flush / close vb? Testprogram bir dosyayı diske yazarsa, dosya en azından mevcut olmalıdır (boş veya değil)


1
2018-04-29 08:27





Web uygulamanız varsa ve harici programınız / işleminiz dosya üretiyorsa (diske yaz) IIS'nizin IIS kullanıcısı için güvenlik ekleme izni yoksa, bu klasöre yazma haklarının olup olmadığını kontrol edin. process.HasExited = true, ancak süreçten dosyalar üretilemedi, bir süre uğraştıktan sonra, sürecin kıvrıldığı klasöre tam izinler ekledim ve Zarathos yukarıdan tarif edildiği gibi process.Refresh () beklendiği gibi çalışıyor.


0
2018-04-18 00:16