Nếu bạn đã từng đào BCL, bạn sẽ thấy rằng các cách để tìm quy trình mẹ được cố tình tránh, lấy ví dụ như sau:
https://referencesource.microsoft.com/#System/services/monitoring/system/diagnosticts/ProcessManager.cs,327
Như bạn có thể thấy trong mã nguồn, nó chứa các cấu trúc toàn diện và các phương thức gốc được nhập hoàn toàn đủ để hoàn thành công việc. Tuy nhiên, ngay cả khi bạn truy cập chúng thông qua phản chiếu (điều này có thể xảy ra), bạn sẽ không tìm thấy phương pháp thực hiện trực tiếp. Tôi không thể trả lời tại sao, nhưng hiện tượng này khiến những câu hỏi như của bạn được đặt ra nhiều lần; ví dụ:
Làm cách nào tôi có thể lấy PID của quy trình chính của đơn đăng ký của tôi
Vì không có câu trả lời cùng với một số mã sử dụng CreateToolhelp32Snapshot trong chủ đề này, tôi sẽ thêm nó vào - một phần của định nghĩa cấu trúc và tên mà tôi lấy cắp từ nguồn tham khảo của MS :)
Mã
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);
}
}
Và chúng ta có thể sử dụng nó như:
Đối với kết thúc thay thế ..
Theo tài liệu, có một cặp phương pháp lặp cho mỗi loại mục nhập, chẳng hạn như Process32First
và Process32Next
dành cho việc lặp lại các quy trình; nhưng tôi thấy các phương thức `xxxxFirst 'là không cần thiết và sau đó tôi nghĩ tại sao không đặt phương thức lặp với loại mục nhập tương ứng của nó? Nó sẽ dễ thực hiện và dễ hiểu hơn (tôi đoán vậy ..).
Cũng giống như Toolhelp32
hậu tố với sự giúp đỡ , tôi nghĩ rằng một lớp helper tĩnh là thích hợp, vì vậy chúng tôi có thể có tên tiêu chuẩn rõ ràng như Toolhelp32.Snapshot
hay Toolhelp32.IEntry
mặc dù nó muốn được liên quan ở đây ..
Sau khi có được quy trình gốc, nếu bạn muốn nhận thêm một số thông tin chi tiết, bạn có thể mở rộng với quy trình này một cách dễ dàng, ví dụ: lặp lại trên các mô-đun của nó, sau đó thêm:
Mã - 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;
}
và một số bài kiểm tra ..
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;
}
}
Trong trường hợp bạn muốn một ví dụ về mã ..