#include <conio.h>
#include <iostream>
#include <exception>
#include <windows.h>
using namespace std;
class CTextException : public exception
{
string m_strText;
public:
CTextException(const char *szText) : m_strText(szText) {};
virtual const char *what() const throw() { return m_strText.c_str(); };
};
int main(int argc, char* argv[])
{
CLSID wordCLSID;
IUnknown *pUnk = NULL;
CoInitialize(NULL);
try
{
if (FAILED(CLSIDFromProgID(L"Word.Application", &wordCLSID)))
throw CTextException("CLSIDFromProgID");
if (FAILED(CoCreateInstance(wordCLSID, NULL,
CLSCTX_LOCAL_SERVER,
IID_IUnknown, (LPVOID *)&pUnk)))
throw CTextException("CoCreateInstance");
}
catch (exception& e)
{
cout << "ERROR: " << e.what() << endl;
}
if (pUnk)
pUnk->Release();
CoUninitialize();
cout << "Done." << endl;
_getch();
return 0;
}
Пробуждение родительского процесса.
Имеется процесс А, изменить (переписать) который нет возможности. Этот процесс запускает с ожиданием завершения процесс B (изменить который возможность есть).
Необходимо сделать так, чтобы процесс A не ожидал завершения B, а продолжал исполняться.
Буду благодарен за любые решения.
Скорее всего процесс А дожидается выполнения процесса В с помощью функции WaitForSingleObject. Второй параметр у нее стоит при этом INFINITE, то есть ждать она будет бесконечно - пока ее первый параметр(хэндл процесса) не перейдет в signal state (функция вернет WAIT_OBJECT_0).
Может просто в процессе А используя инжектирование перехватить эту функцию и подменить у нее второй параметр(если он INFINITE) на 10мс например... тогда функция будет ждать только 10 мс, и потом отдаст управление главной программе...
У меня больше мыслей нет по этому поводу, если есть тут спецы - они должны помочь...
Мне тоже кажется что ничего из B не сделать :( ... Вот если бы можно было послать родителю (A) сигнал, что дочерний процесс (B) завершен... но такого сигнала я в MSDN не обнаружил.
P.S. Если кто-то точно знает что ничего уже не поможет - отпишите пожалуйста тоже :)
А нельзя по-простому? Процессу B вводим некий флажок (хоть через параметр командной строки), работающий след. образом. Процесс А запускает В без этого флажка. При старте В проверяет, установлен ли флаг. Если нет, то В запускает новую копию себя с установленным флажком и завершается (А продолжает выполняться), если установлен - работает обычным образом.
К сожалению, нельзя. Процесс А видимо ждёт завершения всех потомков. К примеру, если в качестве процесса B использовать cmd.exe и запусть из cmd calc то A 'проснётся' только по завершении и cmd и calc.
Я не очень хорошо разбираюсь в процессах windows, может ли процесс симулировать свою смерть, скажем, оправкой какого-либо сигнала? Или может ли B запустить процесс С, но таким образом, чтобы C не был потомком А?
P.S. Буду признателен если тыкните в хорошую доку по устройству процессов в windows.
Спасибо.
Дело в том, что не существует всех потомков. Скорее всего процесс А использует job. Тогда действительно все дочерние процессы попадают в этот job, а процесс А ждет завершения работы всех процессов в job. Симулировать свою смерть процесс не может. Перехват всех Wait-ф-ций у процесса А - ОЧЕНЬ большой геморрой. Попробуй использовать ShellExecute вместо CreateProcess в процессе В (вариант с флажком).
Попробовал. Не помогло.
На крайний случай можно создать ждущий процесс, запускаемый с системой и создающий некий именованный Event. Сигналом к активным действиям будет выставление этого Event'а.
Других идей пока нет.
PS
А есть уверенность, что А не ждет каких-либо конкретных данных? И если нет, то есть ли необходимость бороться с такой защитой?
add/remove programs запускает анинсталлер с ожиданием завершения. Получается, что анинсталлер или любой порождённый им процесс блокирует окно add/remove programs. Соответственно, ожидание закрытия IE блокирует это окно.
Надеюсь, понятно изложил.
Спасибо.
В общем все подтвердилось - процесс действительно попадает в Job.
Обходится через COM (проверено в WinXP Pro SP2). Вот пример.
Код:
Наличие запущенного ворда смотрим через TaskManager (у меня ворд XP не выгружается при pUnk->Release()).
Осталось дело за малым - написать свой uninstaller с использованием COM.
Большое спасибо!