BCL'yi daha önce kazdıysanız, ana süreci bulmanın yollarından kasıtlı olarak kaçınıldığını göreceksiniz, örneğin şunu alın:
https://referencesource.microsoft.com/#System/services/monitoring/system/diagnosticts/ProcessManager.cs,327
Kaynak kodda görebileceğiniz gibi, kapsamlı yapılar ve işin yapılması için kesinlikle yeterli olan içe aktarılmış yerel yöntemler içerir. Ancak, onlara yansıtma yoluyla erişseniz bile (bu mümkündür), bunu doğrudan yapmak için bir yöntem bulamazsınız. Nedenini cevaplayamıyorum, ancak bu fenomen sizinki gibi soruların bir şekilde tekrar tekrar sorulmasına neden oluyor; Örneğin:
Başvurumun ana sürecinin PID'sini nasıl alabilirim
Bu iş parçacığında CreateToolhelp32Snapshot kullanan bazı kodların yanı sıra bir cevap olmadığı için , onu eklerim - MS'nin referans kaynağından çaldığım yapı tanımlarının ve adlarının bir parçası :)
Kod
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System;
public static class Toolhelp32 {
public const uint Inherit = 0x80000000;
public const uint SnapModule32 = 0x00000010;
public const uint SnapAll = SnapHeapList|SnapModule|SnapProcess|SnapThread;
public const uint SnapHeapList = 0x00000001;
public const uint SnapProcess = 0x00000002;
public const uint SnapThread = 0x00000004;
public const uint SnapModule = 0x00000008;
[DllImport("kernel32.dll")]
static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll")]
static extern IntPtr CreateToolhelp32Snapshot(uint flags, int processId);
public static IEnumerable<T> TakeSnapshot<T>(uint flags, int id) where T : IEntry, new() {
using(var snap = new Snapshot(flags, id))
for(IEntry entry = new T { }; entry.TryMoveNext(snap, out entry);)
yield return (T)entry;
}
public interface IEntry {
bool TryMoveNext(Toolhelp32.Snapshot snap, out IEntry entry);
}
public struct Snapshot:IDisposable {
void IDisposable.Dispose() {
Toolhelp32.CloseHandle(m_handle);
}
public Snapshot(uint flags, int processId) {
m_handle=Toolhelp32.CreateToolhelp32Snapshot(flags, processId);
}
IntPtr m_handle;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct WinProcessEntry:Toolhelp32.IEntry {
[DllImport("kernel32.dll")]
public static extern bool Process32Next(Toolhelp32.Snapshot snap, ref WinProcessEntry entry);
public bool TryMoveNext(Toolhelp32.Snapshot snap, out Toolhelp32.IEntry entry) {
var x = new WinProcessEntry { dwSize=Marshal.SizeOf(typeof(WinProcessEntry)) };
var b = Process32Next(snap, ref x);
entry=x;
return b;
}
public int dwSize;
public int cntUsage;
public int th32ProcessID;
public IntPtr th32DefaultHeapID;
public int th32ModuleID;
public int cntThreads;
public int th32ParentProcessID;
public int pcPriClassBase;
public int dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public String fileName;
}
public static class Extensions {
public static Process Parent(this Process p) {
var entries = Toolhelp32.TakeSnapshot<WinProcessEntry>(Toolhelp32.SnapAll, 0);
var parentid = entries.First(x => x.th32ProcessID==p.Id).th32ParentProcessID;
return Process.GetProcessById(parentid);
}
}
Ve bunu şu şekilde kullanabiliriz:
Alternatif son için ..
Belgelere göre, her girdi türü için işlemlerin yinelenmesi gibi Process32First
ve Process32Next
bunlar için bir çift yineleme yöntemi vardır; ancak "xxxxFirst 'yöntemlerinin gereksiz olduğunu buldum ve sonra neden yineleme yöntemini karşılık gelen girdi türüyle birlikte koymadığımı düşündüm? Uygulaması ve anlaşılması daha kolay olurdu (sanırım öyle ..).
Tıpkı Toolhelp32
ile sonlandırılmış yardımı , bir statik yardımcı sınıfı biz gibi berrak nitelikli isimlere sahip olabilir böylece, doğru olduğunu düşünüyorum Toolhelp32.Snapshot
ya Toolhelp32.IEntry
da burada alakasız olurdu gerçi ..
Üst süreç elde edildikten sonra, bazı ayrıntılı bilgileri daha fazla almak istiyorsanız, bununla kolayca genişletebilirsiniz, örneğin, modüllerini yineleyin ve sonra ekleyin:
Kod - WinModuleEntry
[StructLayout(LayoutKind.Sequential)]
public struct WinModuleEntry:Toolhelp32.IEntry {
[DllImport("kernel32.dll")]
public static extern bool Module32Next(Toolhelp32.Snapshot snap, ref WinModuleEntry entry);
public bool TryMoveNext(Toolhelp32.Snapshot snap, out Toolhelp32.IEntry entry) {
var x = new WinModuleEntry { dwSize=Marshal.SizeOf(typeof(WinModuleEntry)) };
var b = Module32Next(snap, ref x);
entry=x;
return b;
}
public int dwSize;
public int th32ModuleID;
public int th32ProcessID;
public int GlblcntUsage;
public int ProccntUsage;
public IntPtr modBaseAddr;
public int modBaseSize;
public IntPtr hModule;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string moduleName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string fileName;
}
ve biraz test ..
public class TestClass {
public static void TestMethod() {
var p = Process.GetCurrentProcess().Parent();
Console.WriteLine("{0}", p.Id);
var formatter = new CustomFormatter { };
foreach(var x in Toolhelp32.TakeSnapshot<WinModuleEntry>(Toolhelp32.SnapModule, p.Id)) {
Console.WriteLine(String.Format(formatter, "{0}", x));
}
}
}
public class CustomFormatter:IFormatProvider, ICustomFormatter {
String ICustomFormatter.Format(String format, object arg, IFormatProvider formatProvider) {
var type = arg.GetType();
var fields = type.GetFields();
var q = fields.Select(x => String.Format("{0}:{1}", x.Name, x.GetValue(arg)));
return String.Format("{{{0}}}", String.Join(", ", q.ToArray()));
}
object IFormatProvider.GetFormat(Type formatType) {
return typeof(ICustomFormatter)!=formatType ? null : this;
}
}
Bir kod örneği istemeniz durumunda ..