JNA GetExitCodeProcess () работает странно - PullRequest
0 голосов
/ 30 сентября 2011

У меня очень странная проблема с JNA.Я проверяю, существует ли процесс, используя GetExitCodeProcess ().

Так, например, я знаю, что блокнот - это PID 2084. Когда я использую свой метод, чтобы проверить, существует ли PID 2084, он возвращает true для PID между 2084 и2087 (хотя я полностью уверен, что PID 2085-2087 не существует).Он возвращает false для других идентификаторов PID, таких как 2083 и 2088.

Это почти как если бы произошла какая-то невозможная ошибка округления, и OpenProcess() открывает дескриптор несуществующего идентификатора PID!

Это происходит со всеми процессами.Если я перечислю все процессы и вызову isRunning (PID), он вернет true, когда существует PID + 1,2 or 3.В противном случае он возвращает false, поэтому, по крайней мере, он работает частично.

Шаблон всегда один и тот же, он возвращает true между PID и PID + 3.

Пример вывода:

[Notepad PID = 2084, cmd.exe PID = 2100]

isRunning(2083)=False
isRunning(2084)=true
isRunning(2085)=true
isRunning(2086)=true
isRunning(2087)=true
isRunning(2088)=false
.... false .....
isRunning(2100)=true

и т.д ..

Interface code:

protected interface Kernel32 extends StdCallLibrary {
        Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class);
        public Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, int dwProcessId);
        int GetLastError();
        boolean GetExitCodeProcess(Pointer hProcess, IntByReference lpExitCode);
    };

Function code:

public static boolean isRunning(int pid)
{
    final int PROCESS_QUERY_INFORMATION = 0x0400;
    final int STILL_ALIVE = 259;
    final int INVALID_PARAM = 87;

    Pointer hProcess = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, false, pid);
    int error = kernel32.GetLastError();

    if (error == INVALID_PARAM)
        return false; //Invalid parameter.

    IntByReference exitCode = new IntByReference();
    kernel32.GetExitCodeProcess(hProcess, exitCode);


    if (exitCode.getValue() != STILL_ALIVE)
        return false;
    else 
        return true;


}



public static void main(String[] args) {
    System.out.println(isRunning(2083)); //Proceses with PID 2083, 2085 to 2088 do not exist.
    System.out.println(isRunning(2084)); //2084 is notepad
    System.out.println(isRunning(2085));
    System.out.println(isRunning(2086));
    System.out.println(isRunning(2087));
    System.out.println(isRunning(2088));
}

Ответы [ 2 ]

2 голосов
/ 30 сентября 2011

Это деталь реализации Windows. 2 младших значащих бита PID игнорируются. Так что в вашем примере 2084-2087 все ссылаются на один и тот же процесс.

Рэймонд Чен уже писал об этом: Почему OpenProcess успешен, даже когда я добавляю три к идентификатору процесса?

Вы бы хорошо прислушались к следующему предостережению:

Опять же, я хочу подчеркнуть, что поведение, которое вы видите в ядрах Windows NT, является просто артефактом реализации, который может измениться в любое время.

0 голосов
/ 01 октября 2011

Отвечая на вопрос, который вы на самом деле не задавали, но здесь находится слон:

Я проверяю, существует ли процесс, используя GetExitCodeProcess ().

Плохая стратегия - идентификаторы процессов используются повторно / перерабатываются, поэтому вполне возможно, что после смерти блокнота с PID 2084 PID будет переработан в какой-то другой случайный процесс, и GetExitCodeProcess может создать ложное впечатление, что блокнот еще жив когда на самом деле это какой-то другой процесс, который, как оказалось, имеет тот же PID, который сейчас активен). Таким образом, может показаться, что все работает нормально, когда вы тестируете свой код на своей машине, но иногда случайно и таинственно терпите неудачу в реальном мире.

Возможно, вы сможете заставить его работать [лучше], если сохраните больше, чем просто PID - например, сохраните также exe-имя (GetModuleFileNameEx), но даже тогда у вас возникнут проблемы, если новый экземпляр того же приложения создается. Сохраните основной HWND слишком для хорошей меры; HWND также перерабатываются, но гораздо медленнее, чем PID.

...