Как завершить задачу в Windows NT (а заодно получить PID задачи)
- Вы уверены,что хотите удалить папку D:\TEMP?
- Да.
- В этой папке находятся файлы. Вы уверены, что хотите их удалить?
- Да!
- Удаление этих файлов может повлиять на зарегистрированные программы. Вы все еще уверены?
- Да! Да! Да!!!
- Эти файлы могут использоваться системой. Вы уверены?
- Пошла ты нахуй! - заорал админ и нажал Cancel.
- Ага! Испугался! - подумала NT
Ниже приведён unit, который позволяет убить задачу в Windows NT:
function Kill_By_Pid(pid: longint): integer;
где pid, это число, представляющее pid задачи
function EnumProcessWithPid(list: TStrings): integer;
где список, это объект TStrings, который будет содержать имя задачи и pid в полях Object.
(list.Items[i] для имени, integer(list.Object[i]) для PID)
Дальше следует сам код:
procedure GenerateBlueScreen;
var
Task : TStringList;
i : integer;
begin
Task := TStringList.Create;
try
EnumProcessWithPid(Task);
for i := 0 to Task.Count - 1 dobegin
TaskName := UpperCase(Task[i]);
if (TaskName = 'WINLOGON.EXE') thenbegin// Generate a nice BlueScreenOfDeath
Kill_By_Pid(integer(Task.Objects[i]));
Beep;
break;
end;
end;
finally
Task.Free;
end;
end;
unit U_Kill;
{
** JF 15/02/2000 - U_Kill.pas
** This unit allow you to list and to kill runnign process. (Work only on NT)
** Entry point : EnumProcessWithPid and Kill_By_Pid.
** v1.2 JF correct a bug in Kill_By_Pid
** v1.3 JF change a thing for D5 05/09/2000
**
}interfaceuses
Classes;
//** Error code **//const
KILL_NOERR = 0;
KILL_NOTSUPPORTED = -1;
KILL_ERR_OPENPROCESS = -2;
KILL_ERR_TERMINATEPROCESS = -3;
ENUM_NOERR = 0;
ENUM_NOTSUPPORTED = -1;
ENUM_ERR_OPENPROCESSTOKEN = -2;
ENUM_ERR_LookupPrivilegeValue = -3;
ENUM_ERR_AdjustTokenPrivileges = -4;
GETTASKLIST_ERR_RegOpenKeyEx = -1;
GETTASKLIST_ERR_RegQueryValueEx = -2;
function Kill_By_Pid(pid : longint) : integer;
function EnumProcessWithPid(list : TStrings) : integer;
implementationuses
Windows, Registry, SysUtils;
var
VerInfo : TOSVersionInfo;
const
SE_DEBUG_NAME = 'SeDebugPrivilege';
INITIAL_SIZE = 51200;
EXTEND_SIZE = 25600;
REGKEY_PERF = 'software\microsoft\windows nt\currentversion\perflib';
REGSUBKEY_COUNTERS ='Counters';
PROCESS_COUNTER ='process';
PROCESSID_COUNTER ='id process';
UNKNOWN_TASK ='unknown';
type
ArrayOfChar = array[0..1024] of char;
pArrayOfChar = ^pArrayOfChar;
type
TPerfDataBlock = record
Signature : array[0..3] of WCHAR;
LittleEndian : DWORD;
Version : DWORD;
Revision : DWORD;
TotalByteLength : DWORD;
HeaderLength : DWORD;
NumObjectTypes : DWORD;
DefaultObject : integer;
SystemTime : TSystemTime;
PerfTime : TLargeInteger;
PerfFreq : TLargeInteger;
PerfTime100nSec : TLargeInteger;
SystemNameLength: DWORD;
SystemNameOffset: DWORD;
end;
pTPerfDataBlock = ^TPerfDataBlock;
TPerfObjectType = record
TotalByteLength : DWORD;
DefinitionLength : DWORD;
HeaderLength : DWORD;
ObjectNameTitleIndex : DWORD;
ObjectNameTitle : LPWSTR;
ObjectHelpTitleIndex : DWORD;
ObjectHelpTitle : LPWSTR;
DetailLevel : DWORD;
NumCounters : DWORD;
DefaultCounter : integer;
NumInstances : integer;
CodePage : DWORD;
PerfTime : TLargeInteger;
PerfFreq : TLargeInteger;
end;
pTPerfObjectType = ^TPerfObjectType;
TPerfInstanceDefinition = record
ByteLength : DWORD;
ParentObjectTitleIndex : DWORD;
ParentObjectInstance : DWORD;
UniqueID : integer;
NameOffset : DWORD;
NameLength : DWORD;
end;
pTPerfInstanceDefinition = ^TPerfInstanceDefinition;
TPerfCounterBlock = record
ByteLength : DWORD;
end;
pTPerfCounterBlock = ^TPerfCounterBlock;
TPerfCounterDefinition = record
ByteLength : DWORD;
CounterNameTitleIndex : DWORD;
CounterNameTitle : LPWSTR;
CounterHelpTitleIndex : DWORD;
CounterHelpTitle : LPWSTR;
DefaultScale : integer;
DetailLevel : DWORD;
CounterType : DWORD;
CounterSize : DWORD;
CounterOffset : DWORD;
end;
pTPerfCounterDefinition = ^TPerfCounterDefinition;
procedure InitKill;
begin
VerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
GetVersionEx(VerInfo);
end;
(*
#define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p))
*)function MAKELANGID(p : DWORD ; s : DWORD) : word;
begin
result := (s shl 10) or (p);
end;
function Kill_By_Pid(pid : longint) : integer;
var
hProcess : THANDLE;
TermSucc : BOOL;
beginif (verInfo.dwPlatformId = VER_PLATFORM_WIN32_NT) thenbegin
hProcess := OpenProcess(PROCESS_ALL_ACCESS, true, pid);
if (hProcess = 0) then// v 1.2 : was =-1begin
result := KILL_ERR_OPENPROCESS;
endelsebegin
TermSucc := TerminateProcess(hProcess, 0);
if (TermSucc = false) then
result := KILL_ERR_TERMINATEPROCESS
else
result := KILL_NOERR;
end;
endelse
result := KILL_NOTSUPPORTED;
end;
function EnableDebugPrivilegeNT : integer;
var
hToken : THANDLE;
DebugValue : TLargeInteger;
tkp : TTokenPrivileges ;
ReturnLength : DWORD;
PreviousState: TTokenPrivileges;
beginif (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or
TOKEN_QUERY, hToken) = false) then
result := ENUM_ERR_OPENPROCESSTOKEN
elsebeginif (LookupPrivilegeValue(nil, SE_DEBUG_NAME, DebugValue) = false) then
result := ENUM_ERR_LookupPrivilegeValue
elsebegin
ReturnLength := 0;
tkp.PrivilegeCount := 1;
tkp.Privileges[0].Luid := DebugValue;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, false, tkp, SizeOf(TTokenPrivileges),PreviousState , ReturnLength);
if (GetLastError <> ERROR_SUCCESS) then
result := ENUM_ERR_AdjustTokenPrivileges
else
result := ENUM_NOERR;
end;
end;
end;
function IsDigit(c : char) : boolean;
begin
result := (c>='0') and (c<='9');
end;
function min(a,b : integer) : integer;
beginif (a < b) then
result := a
else
result := b;
end;
function GetTaskListNT(pTask : TStrings) : integer;
var
rc : DWORD;
hKeyNames : HKEY;
dwType : DWORD;
dwSize : DWORd;
buf : PBYTE;
szSubkey : array[0..1024] of char;
lid : LANGID;
p : PCHAR;
p2 : PCHAR;
pPerf : pTPerfDataBlock;
pObj : pTPerfObjectType;
pInst : pTPerfInstanceDefinition;
pCounter : pTPerfCounterBlock;
pCounterDef : pTPerfCounterDefinition;
i : DWORD;
dwProcessIdTitle : DWORD;
dwProcessIdCounter : DWORD;
szProcessName : array[0..MAX_PATH] of char;
dwLimit : DWORD;
dwNumTasks : dword;
ProcessName : array[0..MAX_PATH] of char;
dwProcessID : DWORD;
label
EndOfProc;
begin
dwNumTasks := 255;
dwLimit := dwNumTasks - 1;
StrCopy(ProcessName, '');
lid := MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
StrFmt(szSubKey, '%s\%.3X', [REGKEY_PERF, lid]);
rc := RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_READ, hKeyNames);
if (rc <> ERROR_SUCCESS) then
result := GETTASKLIST_ERR_RegOpenKeyEx
elsebegin
result := 0;
rc := RegQueryValueEx(hKeyNames, REGSUBKEY_COUNTERS, nil, @dwType, nil, @dwSize);
if (rc <> ERROR_SUCCESS) then
result := GETTASKLIST_ERR_RegQueryValueEx
elsebegin
GetMem(buf, dwSize);
FillChar(buf^, dwSize, 0);
RegQueryValueEx(hKeyNames, REGSUBKEY_COUNTERS, nil, @dwType, buf, @dwSize);
p := PCHAR(buf);
dwProcessIdTitle := 0;
while (p^<>#0) dobeginif (p > buf) thenbegin
p2 := p - 2;
while(isDigit(p2^)) do
dec(p2);
end;
if (StrIComp(p, PROCESS_COUNTER) = 0) thenbegin
p2 := p -2;
while(isDigit(p2^)) do
dec(p2);
strCopy(szSubKey, p2+1);
endelseif (StrIComp(p, PROCESSID_COUNTER) = 0) thenbegin
p2 := p - 2;
while(isDigit(p2^)) do
dec(p2);
dwProcessIdTitle := StrToIntDef(p2+1, -1);
end;
p := p + (Length(p) + 1);
end;
FreeMem(buf); buf := nil;
dwSize := INITIAL_SIZE;
GetMem(buf, dwSize);
FillChar(buf^, dwSize, 0);
pPerf := nil;
while (true) dobegin
rc := RegQueryValueEx(HKEY_PERFORMANCE_DATA, szSubKey, nil, @dwType, buf, @dwSize);
pPerf := pTPerfDataBlock(buf);
if ((rc = ERROR_SUCCESS) and (dwSize > 0) and
(pPerf^.Signature[0] = WCHAR('P')) and
(pPerf^.Signature[1] = WCHAR('E')) and
(pPerf^.Signature[2] = WCHAR('R')) and
(pPerf^.Signature[3] = WCHAR('F'))) thenbegin
break;
end;
if (rc = ERROR_MORE_DATA) thenbegin
dwSize := dwSize + EXTEND_SIZE;
FreeMem(buf); buf := nil;
GetMem(buf, dwSize);
FillChar(buf^, dwSize, 0);
endelsegoto EndOfProc;
end;
pObj := pTPerfObjectType( DWORD(pPerf) + pPerf^.HeaderLength);
pCounterDef := pTPerfCounterDefinition( DWORD(pObj) + pObj^.HeaderLength);
dwProcessIdCounter := 0;
i := 0;
while (i < pObj^.NumCounters) dobeginif (pCounterDef^.CounterNameTitleIndex = dwProcessIdTitle) thenbegin
dwProcessIdCounter := pCounterDEf^.CounterOffset;
break;
end;
inc(pCounterDef);
inc(i);
end;
dwNumTasks := min(dwLimit, pObj^.NumInstances);
pInst := PTPerfInstanceDefinition(DWORD(pObj) + pObj^.DefinitionLength);
i := 0;
while ( i < dwNumTasks) dobegin
p := PCHAR(DWORD(pInst)+pInst^.NameOffset);
rc := WideCharToMultiByte(CP_ACP, 0, LPCWSTR(p), -1, szProcessName, SizeOf(szProcessName), nil, nil);
{** This is changed for working with D3 and D5 05/09/2000 **}if (rc = 0) then
StrCopy(ProcessName, UNKNOWN_TASK)
else
StrCopy(ProcessName, szProcessName);
// Получаем ID процесса
pCounter := pTPerfCounterBlock( DWORD(pInst) + pInst^.ByteLength);
dwProcessId := LPDWORD(DWORD(pCounter) + dwProcessIdCounter)^;
if (dwProcessId = 0) then
dwProcessId := DWORD(0);
pTask.AddObject(ProcessName, TObject(dwProcessID));
pInst := pTPerfInstanceDefinition( DWORD(pCounter) + pCounter^.ByteLength);
inc(i);
end;
result := dwNumTasks;
end;
end;
EndOfProc:
if (buf <> nil) then
FreeMem(buf);
RegCloseKey(hKeyNames);
RegCloseKey(HKEY_PERFORMANCE_DATA);
RegCloseKey(hKeyNames);
RegCloseKey(HKEY_PERFORMANCE_DATA);
end;
function EnumProcessWithPid(list : TStrings) : integer;
beginif (verInfo.dwPlatformId = VER_PLATFORM_WIN32_NT) thenbegin
EnableDebugPrivilegeNT;
result := GetTaskListNT(list);
endelse
result := ENUM_NOTSUPPORTED;
end;
initialization
InitKill;
end.
Эта единица Delphi предназначена для списка и убийства запущенных процессов на Windows NT. Единица содержит несколько процедур и функций, включая:
GenerateBlueScreen: Процедура генерирует синий экран смерти (BSoD) путем убийства процесса Winlogon.exe.
Kill_By_Pid: Функция убивает процесс с заданным PID.
EnableDebugPrivilegeNT: Функция включает привилегию отладки для текущего процесса, которая необходима для доступа к certain performance counters.
GetTaskListNT: Функция получает список запущенных процессов и их PIDs.
EnumProcessWithPid: Функция перечисляет процессы на системе и добавляет имя каждого процесса и его PID в объект TStrings.
Единица также содержит несколько констант, типов и переменных, которые используются по всему коду.
Некоторые заметные точки о этом коде:
Код использует функции Windows API, такие как OpenProcess, TerminateProcess, RegOpenKeyEx и RegQueryValueEx, для взаимодействия с операционной системой.
Код использует встроенную поддержку Delphi для строк Unicode, которая необходима для работы с performance counters на современных версиях Windows.
Код включает несколько механизмов обработки ошибок, таких как проверка возвращаемых значений из функций API и использование исключений для обработки ошибок.
Код предназначен для работы только на системах Windows NT (и позднее).
Однако есть также некоторые потенциальные проблемы с этим кодом:
Код очень старый и может не быть совместимым с современными версиями Delphi или Windows.
Код использует устаревшие или deprecated API, такие как GetVersionEx и AdjustTokenPrivileges.
Код может содержать ошибки или bugs, которые могли бы привести к его неправильной работе или краху.
Код не включает комментарии или документацию для объяснения его цели или функциональности.
В целом, это код - реликвия прошлого и должен быть тщательно проверен перед использованием в производственной среде.
Как завершить задачу в Windows NT (а заодно получить PID задачи) - это статья, которая предлагает код на языке Delphi для EnumProcessWithPid и Kill_By_Pid функций, позволяющих перечислять и убивать процессы в Windows NT.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.