[/在Compact Framework中调用CreateToolhelp32Snapshot失败

问题描述 投票:1回答:4

[嘿,我正在使用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);
c# .net compact-framework windows-ce
4个回答
4
投票
  • 首先,您的句柄检查错误。高位出现在句柄中很常见,导致在将其转换为带符号的int时看起来像负数。您应该检查它不是NULL(0)还是INVALID_HANDLE_VALUE(-1 / 0xffffffff)。
  • 您不应该“调用GetLastError”,而是调用Marshal.GetLastWin32Error()
  • 您尚未在P / Invoke声明中设置SetLastError属性。在C#中,默认值为false,在VB中,默认值为true。
  • 您的PROCESS32实现在哪里?docs clearly statedwLength成员必须在调用之前设置,并且尚不清楚是否在此发生。

作为旁注,Smart Device FrameworkOpenNETCF.ToolHelp namespace已实现并完成了所有这些工作(以防您不想重新发明轮子的情况。


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找到了这个,它解决了我的问题。


0
投票

[如果您没有看到有效的“上一个错误”信息,则可能需要在API的DllImport属性(MSDN reference with code examples)上添加“ SetLastError”属性。根据此属性的文档,应将SetLastError设置为...

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

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

关于您看到的API失败,我没有发现任何明显的副手;您所拥有的代码似乎与示例代码here非常相似。


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);

最重要的是这一行,因为您必须设置procEntry的大小:

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

© www.soinside.com 2019 - 2024. All rights reserved.