1

Тема: AHK: Завершить поток в процессе

Доброй ночи. Помогите пожалуйста.
Вот нашел код для замораживания потока по его иду:

SuspendThread(ThreadID)
{
    if !(hThread := DllCall("OpenThread", "uint", 0x0002, "int", 0, "uint", ThreadID, "ptr"))
        return "Error in OpenThread"
    if (DllCall("SuspendThread", "ptr", hThread) = -1)
        return "Error in SuspendThread", DllCall("CloseHandle", "ptr", hThread)
    return true, DllCall("CloseHandle", "ptr", hThread)
}

Что бы завершить его такой код не работает:

TerminateThread(ThreadID)
{
    if !(hThread := DllCall("OpenThread", "uint", 0x0002, "int", 0, "uint", ThreadID, "ptr"))
        return "Error in OpenThread"

    if (DllCall("TerminateThread","Ptr",hThread,"UInt",0) = -1)
        return "Error in TerminateThread", DllCall("CloseHandle", "ptr", hThread)
    return true, DllCall("CloseHandle", "ptr", hThread)
}

2 (изменено: svoboden, 2017-04-08 01:53:06)

Re: AHK: Завершить поток в процессе

ID может измениться, если это этот пример, то все работает:

Unicode          := A_IsUnicode ? "W" : ""

TH32CS_SNAPPROCESS := 0x00000002
TH32CS_SNAPTHREAD  := 0x00000004 
CreateToolhelp32Snapshot(Flags, th32ProcessID)
{
   return DllCall("CreateToolhelp32Snapshot", "int", Flags, "int", th32ProcessID)
}
 
Process32First(hSnapshot, pe)
{
   global Unicode
   return DllCall("Process32First" . Unicode, "int", hSnapshot, "int", pe)
}
 
Process32Next(hSnapshot, pe)
{
   global Unicode
   return DllCall("Process32Next" . Unicode, "int", hSnapshot, "int", pe)
}
 
Thread32First(hSnapshot, te)
{
   return DllCall("Thread32First", "int", hSnapshot, "int", te)
}
 
Thread32Next(hSnapshot, te)
{
   return DllCall("Thread32Next", "int", hSnapshot, "int", te)
}
 
THREAD_SUSPEND_RESUME := 0x0002
OpenThread(DesiredAccess, InheritHandle, ThreadId)
{
   return DllCall("OpenThread" , "int", DesiredAccess, "int", InheritHandle, "int", ThreadId)
}
 
SuspendThread(hThread)
{
   return DllCall("SuspendThread", "int", hThread)
}
 
ResumeThread(hThread)
{
   return DllCall("ResumeThread", "int", hThread)
}
 
CloseHandle(Handle)
{
   return DllCall("CloseHandle", "int", Handle)
}
 
Gui Add, Button, x10 y5 w75 gL_Update, Обновить
Gui Add, Button, x100 y5 w75 gL_Stop, Stop
Gui Add, Button, x200 y5 w75 gL_Start, Start
Gui Add, ListView, x10 y35 r20 w450 -Multi, PID|имя процесса|статус
LV_ModifyCol(1, 50)
LV_ModifyCol(2, 300)
LV_ModifyCol(3, 50)
Update()
Gui Show
return
 
L_Update:
   Update()
return
 
L_Stop:
   Stop()
return
 
L_Start:
   Start()
return
 
Start()
{
   global TH32CS_SNAPTHREAD, THREAD_SUSPEND_RESUME
   row := LV_GetNext(0, "Focused")
   LV_GetText(id, row)
   hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, id)
   VarSetCapacity(te, 28)
   NumPut(28, te, 0)
   str := ""
   test := Thread32First(hSnapshot, &te)
   while test
   {
      if (id=NumGet(te, 12))
      {
         hThread := OpenThread(THREAD_SUSPEND_RESUME, 0, NumGet(te, 8))
         if (hThread=0)
         {
            LV_Modify(row, "Col3" , "-1 (" . a_lasterror . ")")
            CloseHandle(hSnapshot)
            return
         }
         ret := ResumeThread(hThread)
         CloseHandle(hThread)
      }
      test := Thread32Next(hSnapshot, &te)
   }
   CloseHandle(hSnapshot)
   LV_Modify(row, "Col3" , ret=0 ? 0 : ret-1)
}
 
Stop()
{
   global TH32CS_SNAPTHREAD, THREAD_SUSPEND_RESUME
   row := LV_GetNext(0, "Focused")
   LV_GetText(id, row)
   hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, id)
   VarSetCapacity(te, 28)
   NumPut(28, te, 0)
   test := Thread32First(hSnapshot, &te)
   while test
   {
      if (id=NumGet(te, 12))
      {
         hThread := OpenThread(THREAD_SUSPEND_RESUME, 0, NumGet(te, 8))
         if (hThread=0)
         {
            LV_Modify(row, "Col3" , "-1 (" . a_lasterror . ")")
            CloseHandle(hSnapshot)
               return
         }
         ret := SuspendThread(hThread)
         CloseHandle(hThread)
      }
      test := Thread32Next(hSnapshot, &te)
   }
   CloseHandle(hSnapshot)
   LV_Modify(row, "Col3" , ret+1)
}
 
Update()
{
   global TH32CS_SNAPPROCESS
   LV_Delete()
   hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
   pesize := A_IsUnicode ? 556 : 296
   VarSetCapacity(pe, pesize)
   NumPut(pesize, pe, 0)
   test := Process32First(hSnapshot, &pe)
   while test
   {
      LV_Add("", NumGet(pe,8), StrGet(&pe+36),"?")
      test := Process32Next(hSnapshot, &pe)
   }
   CloseHandle(hSnapshot)
}
 
GuiClose:
   ExitApp
return

3

Re: AHK: Завершить поток в процессе

svoboden, спасибо за ответ, но мне надо убить принудительно поток в процессе, а не остановить его. В процессе много потоков у которых есть свой ид.

Дело в том что я использую одну длл библиотеку, которая подгружается таким образом:


PATH_API := PathCombine(A_ScriptDir, "Open-API.dll")

hModule := DllCall("LoadLibrary", Str, PATH_API)

PathCombine(abs, rel) {
    VarSetCapacity(dest, (A_IsUnicode ? 2 : 1) * 260, 1) ; MAX_PATH
    DllCall("Shlwapi.dll\PathCombine", "UInt", &dest, "UInt", &abs, "UInt", &rel)
    Return, dest
}

но библиотека подгружается в процесс и видна в модулях, я не знаю как ее выгрузить из памяти. FreeLibrary не помогает.
Я тогда нашел такое решение: заморозить процесс, с помощью одной программы убить поток связаный с библиотекой, во второй программе принудительно выгрузить модуль из памяти. А хотелось бы это автоматизировать.

4

Re: AHK: Завершить поток в процессе

Так поток завершается функцией ExitThread.

5 (изменено: Dworkin, 2017-04-11 01:12:56)

Re: AHK: Завершить поток в процессе

Решил проблему. Проблема была в том что поток открывался только с правами на чтение. Заменил с правами на завершение потока и все заработало.

TerminateThread(ThreadID)
{
    if !(hThread := DllCall("OpenThread", "uint", 0x0001, "int", 0, "uint", ThreadID, "ptr"))
        return "Error in OpenThread"

    if (DllCall("TerminateThread","Ptr",hThread,"UInt",0) = -1)
        return "Error in TerminateThread", DllCall("CloseHandle", "ptr", hThread)
    return true, DllCall("CloseHandle", "ptr", hThread)
}