P/Invoking CreateToolhelp32Snapshot failing in Com

2019-01-29 04:20发布

Hey, im doing a little app for my smart phone, using Windows Mobile 6. I'm trying to get all currently running processec, but method CreateToolhelp32Snapshot always returns -1. So now im stuck. I tried to get error with invoking GetLastError() method, but that method returns 0 value. Here is a snippet of my code.

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

3条回答
乱世女痞
2楼-- · 2019-01-29 04:49

If you're not seeing valid "last error" information, perhaps you might need to add the "SetLastError" attribute on the API's DllImport attribute (MSDN reference with code examples). According to the documentation of this attribute, you should set SetLastError to...

...true to indicate that the callee will call SetLastError; otherwise, false. The default is false.

The runtime marshaler calls GetLastError and caches the value returned to prevent it from being overwritten by other API calls. You can retrieve the error code by calling GetLastWin32Error

As for the API failure you're seeing, I don't spot anything obvious offhand; the code you have seems very similar to the sample code here.

查看更多
闹够了就滚
3楼-- · 2019-01-29 04:52
  • First, your handle check is wrong. It's common for the high bit to be on in a handle, causing it to look like a negative number when cast to a signed int. You should be checking that is isn't NULL (0) or INVALID_HANDLE_VALUE (-1 / 0xffffffff).
  • You shouldn't be "invoking GetLastError" but calling Marshal.GetLastWin32Error()
  • You've not set the SetLastError attribute in the P/Invoke declaration. In C# it defaults to false, in VB it defaults to true.
  • Where's your PROCESS32 implementation? The docs clearly state that the dwLength member must be set before the call and it's not clear here if that's happening.

As a side note, the Smart Device Framework's OpenNETCF.ToolHelp namespace has all of this implemented and working (in case you'd rather not reinvent the wheel).

查看更多
在下西门庆
4楼-- · 2019-01-29 04:56

Instead of

CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

use

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

By default CreateToolhelp32Snapshot will try to snapshot the heaps and that can cause an out of memory error.

Found this at https://social.msdn.microsoft.com/Forums/en-US/e91d845d-d51e-45ad-8acf-737e832c20d0/createtoolhelp32snapshot-windows-mobile-5?forum=vssmartdevicesnative and it solved my problem.

查看更多
登录 后发表回答