1

嘿,我正在为我的智能手机做一个小应用程序,使用 Windows Mobile 6。我试图让所有当前正在运行的 processec,但方法 CreateToolhelp32Snapshot 总是返回 -1。所以现在我卡住了。我尝试调用 GetLastError() 方法时出错,但该方法返回 0 值。这是我的代码片段。

private const int TH32CS_SNAPPROCESS = 0x00000002;
[DllImport("toolhelp.dll")]
public static extern IntPtr CreateToolhelp32Snapshot(uint flags, 
                                                     uint processid);

public static Process[] GetProcesses()
    {
        ArrayList procList = new ArrayList();
        IntPtr handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

        if ((int)handle > 0)
        {
            try
            {
                PROCESSENTRY32 peCurr;
                PROCESSENTRY32 pe32 = new PROCESSENTRY32();

                // get byte array to pass to API call
                byte[] peBytes = pe32.ToByteArray();
                // get the first process
                int retval = Process32First(handle, peBytes);
4

4 回答 4

5
  • 首先,您的句柄检查是错误的。句柄中的高位打开是很常见的,导致它在转换为有符号整数时看起来像一个负数。您应该检查它不是 NULL (0) 或 INVALID_HANDLE_VALUE (-1 / 0xffffffff)。
  • 您不应该“调用 GetLastError”,而是调用 Marshal.GetLastWin32Error()
  • 您没有在 P/Invoke 声明中设置 SetLastError 属性。在 C# 中默认为 false,在 VB 中默认为 true。
  • 您的 PROCESS32 实施在哪里?文档明确指出必须在调用之前设置 dwLength 成员,如果发生这种情况,这里还不清楚。

附带说明一下,Smart Device FrameworkOpenNETCF.ToolHelp 命名空间已实现所有这些并且可以正常工作(以防您不想重新发明轮子)。

于 2008-12-26T17:23:02.893 回答
1

代替

CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

采用

private const int TH32CS_SNAPNOHEAPS = 0x40000000;
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPNOHEAPS, 0);

默认情况下,CreateToolhelp32Snapshot 将尝试对堆进行快照,这可能会导致内存不足错误。

在https://social.msdn.microsoft.com/Forums/en-US/e91d845d-d51e-45ad-8acf-737e832c20d0/createtoolhelp32snapshot-windows-mobile-5?forum=vssmartdevicesnative找到了这个,它解决了我的问题。

于 2015-09-22T19:49:42.603 回答
0

如果您没有看到有效的“最后一个错误”信息,您可能需要在 API 的 DllImport 属性上添加“SetLastError”属性(带有代码示例的 MSDN 参考)。根据此属性的文档,您应该将 SetLastError 设置为...

...true 表示被调用者将调用 SetLastError;否则为假。默认值为假。

运行时封送处理程序调用 GetLastError 并缓存返回的值以防止它被其他 API 调用覆盖。您可以通过调用 GetLastWin32Error 来检索错误代码

至于您看到的 API 故障,我没有发现任何明显的临时问题。您拥有的代码似乎与此处的示例代码非常相似。

于 2008-12-26T16:05:20.367 回答
0

这是基于 MSDN 文档的正确实现

private const int INVALID_HANDLE_VALUE = -1;

[Flags]
private enum SnapshotFlags : uint
{
    HeapList = 0x00000001,
    Process = 0x00000002,
    Thread = 0x00000004,
    Module = 0x00000008,
    Module32 = 0x00000010,
    Inherit = 0x80000000,
    All = 0x0000001F,
    NoHeaps = 0x40000000
}

[DllImport("toolhelp.dll"]
private static extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, int th32ProcessID);

[StructLayout(LayoutKind.Sequential)]
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;
};


IntPtr hSnap = CreateToolhelp32Snapshot(SnapshotFlags.Process, 0);

if (hSnap.ToInt64() != INVALID_HANDLE_VALUE)
{
    PROCESSENTRY32 procEntry = new PROCESSENTRY32();
    procEntry.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));

    if (Process32First(hSnap, ref procEntry))
    {
        do
        {

            //do whatever you want here

        } while (Process32Next(hSnap, ref procEntry));
    }
}

CloseHandle(hSnap);

Most importantly is this line, because you must set the size of the procEntry:

procEntry.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));

于 2020-04-17T01:15:27.533 回答