Bir işlemin çalışıp çalışmadığını nasıl öğrenebilirim?


155

Bir referans System.Diagnostics.Processaldığımda, bir işlemin şu anda çalışıp çalışmadığını nasıl bilebilirim?

Yanıtlar:


252

Bu, adıyla yapmanın bir yoludur:

Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
  MessageBox.Show("nothing");
else
  MessageBox.Show("run");

Daha sonra işlem yapmak üzere kimliği almak için tüm işlemleri döngüye alabilirsiniz:

Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
   Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}

Tam da aradığım şey buydu. Bu çok eski bir yazı olmasına rağmen, bana bunun nasıl geçerli C # olduğunu açıklar mısınız? Bundan şüphe etmiyorum, işe yaradığını görüyorum, ancak {} olmadan başka bir şey görmedim.
MatthewD

4
@MatthewD: if/elseYalnızca bir satır uzunluğundaki C # ifadelerinin blok ifadesini belirtmek için süslü parantezleri olması gerekmez. Bu da geçerlidir foreachve forifadeler. Kodlama stiline kadar kaynar.
Hallmanac

Ben de bu konuda biraz araştırma yaptım, bu bilgiyi buldum, ama bilgiyi görmedim for. Yıl c # .net dev ve ben bu tarzı hiç görmedim. Dedikleri gibi, "her gün yeni bir şeyler öğreniyorsun".
Gönderi

3
@MatthewD evet, bu aslında çoğu dil için geçerli (Java gibi). Bunlar gibi tek gömleklerden kaçınmak ve her zaman kıvırcık parantez koymak genellikle iyi bir uygulamadır, çünkü gelecekte her zaman daha fazla ifade eklemeniz gerekebilir, bu durumda parantezler ihtiyacınız olduğunda zaten orada olacaktır. Ancak bunun gibi şeyler için, sadece bir ifadeye ihtiyacınız olduğundan% 100 eminseniz, yapılması ve sözdizimsel olarak geçerli olması iyidir.
David Mordigal

1
İşlemi bulamazsanız, uzantıyı kaldırmayı deneyin. (Örn: .exe)
DxTx

28

Reflektör kullandıktan sonra bulduğum en basit yol bu. Bunun için bir uzantı yöntemi oluşturdum:

public static class ProcessExtensions
{
    public static bool IsRunning(this Process process)
    {
        if (process == null) 
            throw new ArgumentNullException("process");

        try
        {
            Process.GetProcessById(process.Id);
        }
        catch (ArgumentException)
        {
            return false;
        }
        return true;
    }
}

Yöntem, Process.GetProcessById(processId)yöntemi çağırır ProcessManager.IsProcessRunning(processId)ve ArgumentExceptionişlemin olmaması durumunda atar . Nedense ProcessManagersınıf içseldir ...


Bu gerçekten iyi bir cevaptı; ancak, null istisnası bağımsız değişkenine sahip olmamanız gerekir (Çünkü null başvuru istisnası yine de atılmış olur ve istisna ile hiçbir şey yapmazsınız. Ayrıca, Start () öğesini çağırmadıysanız bir InvalidOperationException elde edersiniz) close () yöntemini
çağırdınız veya

16

Senkron çözüm:

void DisplayProcessStatus(Process process)
{
    process.Refresh();  // Important


    if(process.HasExited)
    {
        Console.WriteLine("Exited.");
    }
    else
    {
        Console.WriteLine("Running.");
    } 
}

Asenkron çözüm:

void RegisterProcessExit(Process process)
{
    // NOTE there will be a race condition with the caller here
    //   how to fix it is left as an exercise
    process.Exited += process_Exited;
}

static void process_Exited(object sender, EventArgs e)
{
   Console.WriteLine("Process has exited.");
}

6
İlk seçenek için: sürecin ilk başta başlatılıp başlatılmadığını nasıl bilebilirim?
reshefm

8

reshefm'in hoş bir cevabı vardı; ancak, sürecin hiç başlamamış olduğu bir durumu açıklamaz.

İşte onun yayınladığı değiştirilmiş bir versiyonu.

    public static bool IsRunning(this Process process)
    {
        try  {Process.GetProcessById(process.Id);}
        catch (InvalidOperationException) { return false; }
        catch (ArgumentException){return false;}
        return true;
    }

Onun aslında null başvuru istisnası olduğunu varsayalım onun ArgumentNullException kaldırıldı ve yine de sistem tarafından atılır ve ben de sürecin asla başlamadı veya close () yöntemini kapatmak için kullanılan durumu açıkladı süreci.


Şahsen, ArgumentNullException ne yanlış gitti hakkında çok daha açık olduğundan, bir NullReferenceException daha günlü bir istisna incelerken bir ArgumentNullException görmeyi tercih ediyorum.
Sean

1
@Sean Normalde sizinle aynı fikirdeyim ama bu bir uzatma yöntemidir. Ben sözdizimi verilen bir boş işaretçi istisnası atmak daha uygun olduğunu düşünüyorum, sadece boş nesnelerin çağrı yöntemleri ile daha tutarlı hissediyor.
Aelphaeis

Bu, FirstHandledException olay işleyicisini her seferinde tetikler. Günlüklerini spam yolunun yolu dostum.
Gecikme

6

Bu bir astar olmalıdır:

public static class ProcessHelpers {
    public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}

3

Bu işlevin ne kadar güvenilir olmasını istediğinize bağlıdır. Sahip olduğunuz belirli işlem vakasının hala çalışıp çalışmadığını ve% 100 doğrulukla kullanılabilir olup olmadığını bilmek istiyorsanız, şansınız kalmaz. Bunun nedeni, yönetilen işlem nesnesinden işlemi tanımlamanın yalnızca 2 yolu olmasıdır.

Birincisi İşlem Kimliği. Ne yazık ki, süreç kimlikleri benzersiz değildir ve geri dönüştürülebilir. İşlem listesinde eşleşen bir Kimlik aramak, yalnızca aynı kimliğe sahip bir işlem olduğunu size söyleyecektir, ancak bu sizin işleminiz olmayabilir.

İkinci madde İşlem Tutamağıdır. Id ile aynı sorunu var ve çalışmak daha garip.

Orta düzeyde güvenilirlik arıyorsanız, geçerli işlem listesinin aynı kimliğe sahip bir işlem olup olmadığını kontrol etmek yeterlidir.


1

Process.GetProcesses()gitmek için bir yoldur. Ancak, nasıl çalıştığına bağlı olarak (yani bir hizmet veya normal bir uygulama olarak, bir başlık çubuğuna sahip olsun ya da olmasın) sürecinizi bulmak için bir veya daha fazla farklı kriter kullanmanız gerekebilir.


Bu yöntemi bir döngüye koyarsanız, çok fazla CPU döngüsüne mal olur. GetProcessByName () veya GetProcessByID () kullanmanızı öneririz.
Hao Nguyen

0

Belki (muhtemelen) soruyu yanlış okuyorum, ancak Process nesneniz tarafından temsil edilen işlemin (normalde ya da değil) çıktığını söyleyen HasExited özelliğini mi arıyorsunuz?

Başvurunuzun bir kullanıcı arayüzü varsa, kullanıcı arayüzünün o anda kullanıcı girdisine yanıt verip vermeyeceğini belirlemek için Yanıtlama özelliğini kullanabilirsiniz.

Ayrıca EnableRaisingEvents öğesini ayarlayabilir ve (asenkron olarak gönderilen) Exited olayını işleyebilir veya engellemek istiyorsanız WaitForExit () öğesini çağırabilirsiniz.


0

İstediğiniz işlem için bir İşlem örneğini bir kez başlatabilir ve bu .NET İşlem nesnesini kullanarak işlemi izlemeye devam edebilirsiniz (izlediği işlem ölmüş olsa bile, bu .NET nesnesini açıkça Kapat'ı çağırıncaya kadar izlemeye devam eder. [bu size işlemin yakın zamanını verebilir, yani ExitTime vb.])

Son teklif http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :

İlişkili bir işlem çıktığında (yani, işletim sistemi tarafından normal veya anormal bir sonlandırma yoluyla kapatıldığında), sistem işlemle ilgili yönetim bilgilerini depolar ve WaitForExit adlı bileşene geri döner. Process bileşeni daha sonra ExitTime içeren bilgilere erişilen işleme tanıtıcıyı kullanarak erişebilir.

İlişkili işlemden çıkıldığından, bileşenin Handle özelliği artık varolan bir işlem kaynağına işaret etmez. Bunun yerine, tanıtıcı yalnızca işletim sisteminin işlem kaynağı hakkındaki bilgilerine erişmek için kullanılabilir. Sistem, İşlem bileşenleri tarafından yayımlanmamış çıkış işlemlerinin tutamaçlarının farkındadır, bu nedenle İşlem bileşeni özellikle kaynakları serbest bırakana kadar ExitTime ve Handle bilgilerini bellekte tutar. Bu nedenle, bir İşlem örneği için Başlat'ı her aradığınızda, ilişkili işlem sona erdiğinde ve artık bununla ilgili herhangi bir yönetim bilgisine ihtiyacınız olmadığında Kapat'ı çağırın. Kapat, çıkış işlemine ayrılan belleği serbest bırakır.


0

Coincoin'in çözümünü denedim:
Bir dosyayı işlemeden önce geçici bir dosya olarak kopyalayıp açıyorum.
İşim bittiğinde, uygulamayı hala açıksa kapatıyorum ve geçici dosyayı siliyorum:
Sadece bir İşlem değişkeni kullanıyorum ve daha sonra kontrol ediyorum:

private Process openApplication;  
private void btnOpenFile_Click(object sender, EventArgs e) {  
    ...
    // copy current file to fileCache  
    ...  
    // open fileCache with proper application
    openApplication = System.Diagnostics.Process.Start( fileCache );  
}

Daha sonra uygulamayı kapatıyorum:

 ...   
openApplication.Refresh(); 

// close application if it is still open       
if ( !openApplication.HasExited() ) {
    openApplication.Kill();  
}

// delete temporary file  
System.IO.File.Delete( fileCache );

Çalışıyor (şimdiye kadar)


3
At openApplication.HasExited(), HasExited bir işlev değildir. Doğru yol olurdu openApplication.HasExited.
caiosm1005

0

.Net çerçevelerinden desteklenen süreçlerin süreç kimliğiyle kontrol edilmesine rağmen, bu işlevler çok yavaştır. Process.GetProcesses () veya Process.GetProcessById / Name () yöntemini çalıştırmak çok miktarda CPU döngüsüne mal olur.

Çalışan bir işlemi kimliğe göre denetlemek için çok daha hızlı bir yöntem, yerel API OpenProcess () kullanmaktır . Dönüş tanıtıcısı 0 ise işlem mevcut değildir. Tanıtıcı 0'dan farklıysa, işlem çalışıyor demektir. Bu yöntemin izin nedeniyle her zaman% 100 çalışacağının garantisi yoktur.


0

Diğerleri kısmen ele aldığı gibi, bununla ilişkili birçok sorun var:

  • Hiçbir örnek üyesinin iş parçacığı açısından güvenli olduğu garanti edilmez. Yani nesnenin özelliklerini değerlendirmeye çalışırken anlık görüntünün kullanım ömrü boyunca oluşabilecek yarış koşulları vardır.
  • İşlem tanıtıcısı, bu ve diğer bu tür özellikleri değerlendirme izinlerine izin verilmeyen ACCESS DENIED için Win32Exception kurar.
  • ISN'T RUNNING durumu için, bazı özelliklerini değerlendirmeye çalışırken bir ArgumentException durumu da oluşturulur.

Diğerlerinin bahsettiği mülkler içsel olsun ya da olmasın, izin verirse yine de yansıma yoluyla onlardan bilgi alabilirsiniz.

var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);

Anlık Görüntü için Win32 kodunu iğneleyebilir veya daha yavaş olan WMI kullanabilirsiniz .

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);

Başka bir seçenek OpenProcess olacaktır / CloseProcess olacaktır, ancak istisnalar daha önce olduğu gibi atılmaya devam edecek.

WMI - OnNewEvent.Properties ["?"] İçin:

  • "ParentProcessID"
  • "ProcessID"
  • "İşlem adı"
  • "SECURITY_DESCRIPTOR"
  • "Oturum kimliği"
  • "Sid"
  • "TIME_CREATED"

0
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
    MessageBox.Show("Working");
}
else
{
    MessageBox.Show("Not Working");
}

ayrıca her zaman süreci kontrol etmek için bir zamanlayıcı kullanabilirsiniz


3
Bunun tersi olmaz mıydı? uzunluk == 0 ise bu çalışmıyor demektir?
Jay Jacobs

Cevap Patrick Desjardins ile aynıdır: stackoverflow.com/a/262291/7713750
Rekshino

Bunun uzunluğu> 0 civarında olması, işlemlerin bulunduğu anlamına gelir.
HaseeB Mir

Bunun bir hatası olabilir, ( length == 0görüntülenmelidir Not Working) ancak yine de işi bitirir.
Momoro
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.