убить "нежно" процесс
, надо закрыть программу
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.146] |
|
|
Правила раздела Visual C++ / MFC / WTL (далее Раздела)
FAQ Раздела
Обновления для FAQ Раздела
Поиск по Разделу
MSDN Library Online
убить "нежно" процесс
, надо закрыть программу
|
Сообщ.
#1
,
|
|
|
|
Есть запущенная программа, могу найти ее handle, как завершить ее, послав ей сообщение WM_CLOSE, или другое че-нить, короче надо так, чтоб она завершилась нормально (в частности надо закрыть 1с, если TerminateProcess(), то она аварийно закрывается). Вот , бьюсь как через handle получить hwnd.
|
|
Сообщ.
#2
,
|
|
|
|
Может лучше через процесс?
А окно проще найти через FindWindow... Например так: ![]() ![]() HWND window; window=FindWindow(0, "Имя окна"); SendMessage(window,WM_CLOSE,0,0); Но я так и не понял, что конкретно тебе нужно... |
|
Сообщ.
#3
,
|
|
|
|
Хочу заметить, что хендл окна это и есть HWND
|
|
Сообщ.
#4
,
|
|
|
|
Приведенный ниже код "нежно" убьет даже svchost.exe
![]() ![]() namespace API_KILLPROCESSNOW { BOOL EnableTokenPrivilege( IN HANDLE htok, IN LPCTSTR szPrivilege, IN OUT TOKEN_PRIVILEGES &tpOld) { TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if( LookupPrivilegeValue( NULL, szPrivilege, &tp.Privileges[0].Luid)) { DWORD cbOld = sizeof( tpOld); if( AdjustTokenPrivileges( htok, FALSE, &tp, cbOld, &tpOld, &cbOld)) return ( ERROR_NOT_ALL_ASSIGNED != GetLastError()); else return FALSE; } return FALSE; } BOOL RestoreTokenPrivilege( IN HANDLE htok, IN const TOKEN_PRIVILEGES &tpOld) { return AdjustTokenPrivileges( htok, FALSE, const_cast<TOKEN_PRIVILEGES*>(&tpOld), 0, 0, 0); } BOOL EnablePrivilege( IN LPCTSTR szPrivilege) { HANDLE hToken; if( !::OpenProcessToken( ::GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE; TOKEN_PRIVILEGES tpOld; BOOL bReturn = EnableTokenPrivilege( hToken, szPrivilege, tpOld); ::CloseHandle(hToken); return bReturn; } BOOL AdjustDacl( IN HANDLE h, IN DWORD DesiredAccess) { SID world = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, 0 }; EXPLICIT_ACCESS ea = { DesiredAccess, SET_ACCESS, NO_INHERITANCE, { 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, reinterpret_cast<LPTSTR>(&world) } }; PACL pdacl = NULL; DWORD err = SetEntriesInAcl( 1, &ea, 0, &pdacl); if( err == ERROR_SUCCESS) { err = SetSecurityInfo( h, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, pdacl, 0); LocalFree( pdacl); return err == ERROR_SUCCESS; } return FALSE; } HANDLE GetProcessHandleWithEnoughRights( IN DWORD PID, IN DWORD AccessRights) { HANDLE hProcess = ::OpenProcess( AccessRights, FALSE, PID); if( !hProcess) { HANDLE hpWriteDAC = OpenProcess( WRITE_DAC, FALSE, PID); if( !hpWriteDAC) { HANDLE htok; if( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &htok)) return FALSE; TOKEN_PRIVILEGES tpOld; if( EnableTokenPrivilege( htok, SE_TAKE_OWNERSHIP_NAME, tpOld)) { HANDLE hpWriteOwner = OpenProcess( WRITE_OWNER, FALSE, PID); if( hpWriteOwner) { BYTE buf[512]; // this should always be big enough DWORD cb = sizeof( buf); if( GetTokenInformation( htok, TokenUser, buf, cb, &cb)) { DWORD err = SetSecurityInfo( hpWriteOwner, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, reinterpret_cast<TOKEN_USER*>(buf)->User.Sid, 0, 0, 0); if( err == ERROR_SUCCESS) { if ( !DuplicateHandle( GetCurrentProcess(), hpWriteOwner, GetCurrentProcess(), &hpWriteDAC, WRITE_DAC, FALSE, 0) ) { hpWriteDAC = NULL; } } } ::CloseHandle( hpWriteOwner); } RestoreTokenPrivilege( htok, tpOld); } ::CloseHandle( htok); } if( hpWriteDAC) { AdjustDacl( hpWriteDAC, AccessRights); if ( !DuplicateHandle( GetCurrentProcess(), hpWriteDAC, GetCurrentProcess(), &hProcess, AccessRights, FALSE, 0) ) { hProcess = NULL; } CloseHandle(hpWriteDAC); } } return hProcess; } BOOL SlayProcess( IN DWORD PID) { HANDLE hp = GetProcessHandleWithEnoughRights( PID, PROCESS_TERMINATE); if( hp) { BOOL bReturn = TerminateProcess( hp, 1); ::CloseHandle(hp); return bReturn; } return FALSE; } }; int KillProccessByID( DWORD processID , CString name) { CString m_strPName; char szProcessName[MAX_PATH] = "unknown"; char szPath[MAX_PATH] = "unknown"; static counter = 0; HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID ); if (NULL != hProcess ) { HMODULE hMod; DWORD cbNeeded; if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) ) { GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName) ); GetModuleFileNameEx(hProcess, hMod, szPath, sizeof(szPath)); } else return counter; } else return counter; counter ++; m_strPName = (LPCTSTR)szPath; m_strPName.MakeUpper(); if (strstr(m_strPName, name)) API_KILLPROCESSNOW::SlayProcess( processID ); return counter; CloseHandle( hProcess ); } а вот как это все вызвать: ![]() ![]() DWORD aProcesses[1024], cbNeeded, cProcesses; if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) return; cProcesses = cbNeeded / sizeof(DWORD); for (UINT i = 0; i < cProcesses; i++ ) KillProccessByID( aProcesses[i], "ИМЯ ТВОЕГО ПРОЦЕССА"); |
|
Сообщ.
#5
,
|
|
|
|
Цитата Вот указатель на процесс я уже нашел, но как его еще можно "убить" кроме как TerminateProcess()? а данная функция для 1с приводит к аварийному закрытию, т.е. не сама она все закрывает, и приходится каждый раз переиндексировать таблицы после такой опреации. Поиск по окну мне кажется не очень оптимальным, т.к. разные конфы могут быть запущены, названия окна может поменяться ..., а так я нахожу процесс инициированный из *.exe 1с программы и пытаюсь его закрыть.SimBiOd Может лучше через процесс? А окно проще найти через FindWindow... Цитата Metatron Хочу заметить, что хендл окна это и есть HWND Это я понимаю, но HWND это указатель на структуру, а у меня handle, т.е. я имел в виду простой указатель на процесс (OpenProcess() его возвращает) (незнаю на что он указывает, наверно на точку входа или еще ченить)Dr_ShpitsVogel Цитата BOOL SlayProcess( IN DWORD PID) { HANDLE hp = GetProcessHandleWithEnoughRights( PID, PROCESS_TERMINATE); if( hp) { BOOL bReturn = TerminateProcess( hp, 1);//***************** ::CloseHandle(hp); return bReturn; } return FALSE; } }; Спасибо за пример, нашел в нем много интересного, но все сводится к томуже TerminateProcess(), который мне неподходит... |
|
Сообщ.
#6
,
|
|
|
|
Можно так:
![]() ![]() BOOL CALLBACK EnumWndProc(HWND hWnd, LPARAPM pid) { DWORD wndpid; GetWindowThreadProcessId(hWnd, &wndpid); if (wndpid != pid) return TRUE; PostMessage(hWnd, WM_CLOSE, 0, 0); } void KillProcessSoftly(DWORD pid) { EnumDesktopWindows(NULL, EnumWndProc, pid); } Т. е. ты перебираешь все окна на десктопе пока не найдешь то, которое принадлежит заданному процессу, после чего посылаешь этому окну WM_CLOSE. На вход этой функции нужен Process Id. |
|
Сообщ.
#7
,
|
|
|
|
Flex Ferrum спасибо, работает как надо
|
|
Сообщ.
#8
,
|
|
|
|
при более тщательном осмотре столкнулся с проблемой, когда посылается сообщение WM_CLOSE, то выскакивает MessageBox или Диалог ("действительно ли вы хотите выйти из прогрммы?"), где надо нажать кнопку Да или Ok. Вот решил эту проблему следующим образом:
Заранее говорю, что практики работы с окнами мало, и нижеприведенный код не претендует на оптимальность и т.д., безусловно есть много других способов более практичных. ![]() ![]() BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam) { char str[50]; DWORD wndpid; GetWindowThreadProcessId(hwnd, &wndpid); if(wndpid!=lParam) return TRUE; GetWindowText(hwnd,str,sizeof(str)); if(strstr(str,"Да")||strstr(str,"Ok")||strstr(str,"OK")) { int id=GetDlgCtrlID(hwnd); hwnd=GetParent(hwnd); SendMessage(hwnd,WM_COMMAND,LOWORD(id),0); }; return TRUE; } BOOL CALLBACK EnumWndProc(HWND hWnd, long pid) { DWORD wndpid;char str[255]; //GetWindowModuleFileName(hWnd,str,sizeof(str)); - никак не запускается, файлы *.h и *.lib подключены GetWindowThreadProcessId(hWnd, &wndpid); if (wndpid != pid) return TRUE; PostMessage(hWnd, WM_CLOSE, 0, 0); HWND hw=GetLastActivePopup(hWnd); if(hw!=hWnd) EnumChildWindows(hw,EnumChildProc,pid); } |
|
Сообщ.
#9
,
|
|
|
|
А почему бы вместо WM_CLOSE не слать WM_QUIT ?
Тогда, вроде, вообше никакие окна с подтверждениями не выскакивают. |