P/Invoke CreateToolhelp32Snapshot сбоя в Compact Framework
Эй, я делаю небольшое приложение для своего смартфона, используя 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);
Ответы
Ответ 1
- Во-первых, проверка вашего дескриптора неверна. Это обычное для того, чтобы высокий бит был включен в дескриптор, заставляя его выглядеть как отрицательное число при нажатии на подписанный int. Вы должны проверить, что это не NULL (0) или INVALID_HANDLE_VALUE (-1/0xffffffff).
- Вы не должны "вызывать GetLastError", но вызывать Marshal.GetLastWin32Error()
- Вы не установили атрибут SetLastError в объявлении P/Invoke. В С# по умолчанию установлено значение false, в VB значение по умолчанию - true.
- Где ваша реализация PROCESS32? В docs четко указывается, что элемент dwLength должен быть установлен перед вызовом, и это неясно здесь, если это происходит.
В качестве дополнительной заметки Smart Device Framework OpenNETCF. Пространство имен ToolHelp имеет все это реализовано и работает (в случае, если вы предпочитаете не изобретать колесо).
Ответ 2
Вместо
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, и он решил мою проблему.
Ответ 3
Если вы не видите действительную "последнюю ошибку", возможно, вам может понадобиться добавить атрибут "SetLastError" в атрибуте API DllImport (MSDN ссылка с примерами кода). Согласно документации этого атрибута, вы должны установить SetLastError в...
... true, чтобы указать, что вызываемый вызовите SetLastError; в противном случае - false. Значение по умолчанию - false.
Вызов маршаллера времени выполнения GetLastError и кэширует значение вернулся, чтобы предотвратить его перезаписываются другими вызовами API. Вы может получить код ошибки, вызвав GetLastWin32Error
Что касается ошибки API, которую вы видите, я не вижу ничего очевидного; код, который вы видите, очень похож на пример кода здесь.