Как я могу отслеживать активность в процессе, который я породил?

Мне было поручено пытаться отслеживать активность всех программ с графическим интерфейсом, порожденных начальной программой, и убивать их, когда они становятся неактивными в течение заданного периода времени. Это не может быть системной активностью, так как мы должны закрывать программы, даже если пользователь какое-то время просто использует другую программу (не порожденную исходной программой). Процессы запуска приложений — это программа .Net, и это не изменится. Я был в состоянии использовать SetWindowsHookEx установить низкоуровневые крючки (WH_KEYBOARD_LL а также WH_MOUSE_LL) из .Net, но не был уверен, как связать сообщения с процессами, которые я начал (используя System.Diagnostics.Process.) Я мог бы перехватывать события из приложения, выполняющего перехват, но он всегда заканчивался неудачей, когда я пытался перехватить определенный поток для порожденной программы.

Самым близким, что я смог прийти, было создание C ++ dll, который вызывает SetWindowsHookEx от имени программы .Net. Используя этот метод, я могу подключиться к первому потоку порожденного notepad.exe, но функция обратного вызова никогда не вызывается. Если я укажу идентификатор потока, равный 0, обратный вызов вызывается, когда в исходном приложении есть активность, поэтому я знаю SetWindowsHookEx работает в таком случае.

Я еще не полностью понимаю перехват, но из того, что я прочитал, это не сработает, потому что адрес функции обратного вызова dll будет бессмысленным для перехваченного процесса. Это проблема, с которой я сталкиваюсь? Если да, есть ли способ обойти это или кто-то может предложить альтернативу, чтобы определить, активно ли используется порожденный процесс?

.Чистый (C #) код:

private const int WH_MOUSE = 14;

[DllImport("TestHook.dll", EntryPoint="InitializeHook",  SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
private static extern bool InitializeHook(uint hookType, int threadID);

private void HookEm() {
//...
System.Diagnostics.Process testProcess = System.Diagnostics.Process.Start("notepad");
if(!InitializeHook(WH_MOUSE, testProcess.Threads[0].Id)) // The notepad.exe thread I know hooks
MessageBox.Show("Boom!");
//...
}

C ++ dll:

HHOOK hookValue;

bool InitializeHook(UINT hookID, int threadID) {
//... Determining which callback to use
hookValue = SetWindowsHookEx(hookID, (HOOKPROC)MouseHookCallback, _dllInstance, threadID);
//...
return hookValue != NULL
}

static LRESULT CALLBACK MouseHookCallback(int code, WPARAM wparam, LPARAM lparam) {
//From what I can see, this is never touched when hooking a thread on an outside process
}

Все это в настоящее время выполняется на 32-битном компьютере с Windows XP. Я понимаю, что отдельная 64-битная DLL будет необходима для работы с порожденными 64-битными приложениями.

3

Решение

Для тех, кто сталкивается с подобной проблемой, наше окончательное решение состояло в том, чтобы проверить окно переднего плана с интервалом, используя GetWindowThreadProcessId(GetForegroundWindow(), ref foregroundWindowProcessId) и ведение карты наших порожденных идентификаторов процессов. Каждый раз, когда срабатывает этот таймер, мы устанавливаем логическое значение для проверки функции, которая вызывает CallNextHookEx так как это должно быть эффективно / быстро, иначе окна отцепят нас. Затем мы используем вышеуказанное логическое значение, и система перехватывает SetWindowsHookEx определить, активен ли пользователь в нашем приложении. Для этого решения не требовался C ++ dll.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]