C#中的`PROCESSENTRY32W`?

Cub*_*i73 6 c# structlayout

我声明了这个函数Process32FirstW和结构PROCESSENTRY32W:

[DllImport("KERNEL32.DLL", CallingConvention = CallingConvention.StdCall, EntryPoint = "Process32FirstW")]
private static extern bool Process32FirstW (IntPtr hSnapshot, ref ProcessEntry pProcessEntry);

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Size = 568)]
internal struct ProcessEntry {
    [FieldOffset(0)] public int Size;
    [FieldOffset(8)] public int ProcessId;
    [FieldOffset(32)] public int ParentProcessID;
    [FieldOffset(44), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string ExeFile;
}
Run Code Online (Sandbox Code Playgroud)

在调用时Process32FirstW(使用64位进程),我总是TypeLoadException说一句话

ProcessEntry无法加载类型,因为偏移44处的对象字段对齐错误或与另一个字段重叠,而另一个字段不是对象字段.

我也尝试使用char[],而不是stringProcessEntry.ExeFile使用Pack=4,并Pack=8在该结构的StructLayoutAttribute.我总是设置ProcessEntry.Size为568,我从C++程序(64位版本)复制了偏移数据:

typedef unsigned long long ulong;
PROCESSENTRY32W entry;

wcout << sizeof(PROCESSENTRY32W) << endl;                           // 568
wcout << (ulong)&entry.dwSize - (ulong)&entry << endl;              // 0
wcout << (ulong)&entry.th32ProcessID - (ulong)&entry << endl;       // 8
wcout << (ulong)&entry.th32ParentProcessID - (ulong)&entry << endl; // 32
wcout << (ulong)&entry.szExeFile - (ulong)&entry << endl;           // 44
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚,出了什么问题,那么如何 PROCESSENTRY32W 在C#中为64位应用程序声明?我是否必须使用C++/CLI或者我在这里做错了什么?


编辑:作为64位程序运行此代码对我来说非常好

HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

PROCESSENTRY32W entry;
entry.dwSize = sizeof(PROCESSENTRY32W);

if (Process32FirstW(hSnapshot, &entry)) {
    do {
        // Do stuff
    } while (Process32NextW(hSnapshot, &entry));
}

CloseHandle(hSnapshot);
Run Code Online (Sandbox Code Playgroud)

Sco*_*ain 5

PROCESSENTRY32被完全定义为

typedef struct tagPROCESSENTRY32 {
  DWORD     dwSize;
  DWORD     cntUsage;
  DWORD     th32ProcessID;
  ULONG_PTR th32DefaultHeapID;
  DWORD     th32ModuleID;
  DWORD     cntThreads;
  DWORD     th32ParentProcessID;
  LONG      pcPriClassBase;
  DWORD     dwFlags;
  TCHAR     szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;
Run Code Online (Sandbox Code Playgroud)

你忽略了ULONG_PTR th32DefaultHeapID;,该成员是4个字节的32位系统和64个系统上8个字节,这意味着你FieldOffsetAttributeParentProcessIDExeFile将取决于如果您正在运行32位和64位不同的偏移。查看您的数学运算,您似乎假设它始终是8个字节。

最简单的解决方法是不明确定义偏移量,而是IntPtr动态地计算出正确的偏移量。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct PROCESSENTRY32 
{ 
   public uint dwSize; 
   public uint cntUsage; 
   public uint th32ProcessID; 
   public IntPtr th32DefaultHeapID; 
   public uint th32ModuleID; 
   public uint cntThreads; 
   public uint th32ParentProcessID; 
   public int pcPriClassBase; 
   public uint dwFlags; 
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)] public string szExeFile; 
 }; 
Run Code Online (Sandbox Code Playgroud)