Лекция 3 GetLastError

Процессы и потоки

· Процесс - это экземпляр выполняемой программы. Процессу отводится 4 Гб адресного пространства. Процесс в Win32 является инертным, т.е. он ничего не выполняет, а только владеет адресным пространством, куда загружаются код и данные EXE файла и DLL библиотек.

Так как процессы инертны, чтобы выполнить код программы необходимо создать поток. У процесса потоков может быть несколько. Все они будут выполнять код программы "одновременно".

Чтобы все потоки работали, ОС выделяет каждому из них определенные отрезки времени, которые называются квантами. Время выделяется по принципу карусели.

Функция создания процесса

function CreateProcess (lpApplicationName: PChar;

lpCommandLine: PChar;

lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;

bInheritHandles: BOOL;

dwCreationFlags: DWORD;

lpEnvironment: Pointer;

lpCurrentDirectory: PChar;

const lpStartupInfo: TStartupInfo;

var lpProcessInformation: TProcessInformation): BOOL;

Функция создает объект ядра - процесс, создает виртуальное адресное пространство 4 Гб, загружает в него код и данные EXE файла. Далее ОС создает объект ядра - первичный поток процесса. Первичный поток начинает работу со стартового кода. При удачном создании процесса функция вернет TRUE, иначе False. Код ошибки можно узнать, вызвав функцию function GetLastError: DWORD.

lpCommandLine - командная строка, содержащая имя выполняемого файла и параметры командной строки. Например, Pchar('notepad.exe myfile.txt'). Функция начинает искать заданный файл в следующем порядке:

1. Каталог, содержащий EXE-файл вызывающего процесса

2. Текущий каталог вызывающего процесса

3. Системный каталог Windows

4. Основной каталог Windows

5. Каталоги, перечисленные в переменной окружения PATH

Все это произойдет, если в LpCommandLine не указан путь по EXE-файла и если lpApplicationName = nil. Если lpApplicationName - строка не пустая система считает, что в ней задано имя выполняемой программы, причем находящейся в текущем каталоге.

lpProcessAttributes, lpThreadAttributes - атрибуты защиты для процесса и первичного потока.

bInheritHandles - флаг наследования.

dwCreationFlags - определяет флаги, влияющие на то, как именно создается новый процесс.

DEBUG_PROCESS - позволяет родительскому процессу проводить отладку всех дочерних процесса. Родительский процесс уведомляется о наступлении определенных событий.

DEBUG_ONLY_THIS_PROCESS - позволяет родительскому процессу проводить отладку только прямого потомка

CREATE_SUSPENDED - приостанавливает выполнение первичного потока

DETACHED_PROCESS -???

CREATE_NEW_CONSOLE - приводит к созданию нового консольного окна

CREATE_NO_WINDOW - не дает создавать консольное окно

CREATE_NEW_PROCESS_GROUP -???

CREATE_DEFAULT_ERROR_MODE - запрещает наследования режимов обработки событий

CREATE_SEPARATE_WOW_VDM - используется для запуска 16 разрядных приложений в Windows NT. Заставляет открывать для процесса отдельную Virtual DOS-machine (VDM). В Windows 95 все DOS приложения выполняются в одной VDM.

CREATE_SHARED_WOW_VDM - имеет обратное действие.

CREATE_UNICODE_ENVIRONMENT - определяет, что переменные окружения содержат Unicode-символы. По умолчанию ANSI символы.

При создании процесса можно указать его класс приоритета:

NORMAL_PRIORITY_CLASS-

IDLE_PRIORITY_CLASS-

HIGH_PRIORITY_CLASS-

REALTIME_PRIORITY_CLASS-

lpEnvironment - Параметр указывает на блок памяти, хранящий строки переменных окружения нового процесса. Если nil - тогда переменные окружения наследуются от родительского процесса.

lpCurrentDirectory - позволяет установить текущий диск и каталог для создаваемого процесса. Если nil то текущий каталог и диск устанавливается такой же, как и у родительского процесса.

lpStartupInfo - элементы данной структуры определяют различные атрибуты при создании нового процесса. Обычно используются атрибуты по умолчанию, поэтому необходимо заполнить данную структуру нулями и записать в lpStartupInfo.cb размер структуры.

Пример:

Var si:TStartupInfo;

begin

ZeroMemory(@si,SizeOf(si));

si.cb:=SizeOf(si);

end;

lpProcessInformation - возвращает информацию о созданном процессе и его первичном потоке.

TProcessInformation = record

hProcess: THandle;

hThread: THandle;

dwProcessId: DWORD;

dwThreadId: DWORD;

end;

dwProcessId, dwThreadId - уникальные идентификаторы процесса и потока

Пример:

procedure TForm1.Button1Click(Sender: TObject);

var

si:TStartupInfo;

pi:TProcessInformation;

begin

ZeroMemory(@si,SizeOf(si));

si.cb:=SizeOf(si);

if not CreateProcess

(nil,

PChar('notepad.exe'),

nil, //lpProcessAttributes

nil, //lpThreadAttributes: PSecurityAttributes;

True, //bInheritHandles: BOOL;

NORMAL_PRIORITY_CLASS,//dwCreationFlags: DWORD;

nil, // lpEnvironment: Pointer;

nil, //lpCurrentDirectory: PChar;

si, //const lpStartupInfo: TStartupInfo;

pi)

then raise Exception.Create(SysErrorMessage(GetLastError));

LabelProcID.Caption:='ID процесса $'+IntToHex(pi.dwProcessId,32);

LabelThreadID.Caption:='ID потока $'+IntToHex(pi.dwThreadID,32);

// закрываем

if not CloseHandle(pi.hThread)

then raise Exception.Create(SysErrorMessage(GetLastError));

if not CloseHandle(pi.hProcess)

then raise Exception.Create(SysErrorMessage(GetLastError));

end;

Несколько полезных функций, относящихся к процессу.

function GetCommandLine: PChar; - возвращает командную строку процесса.

function GetEnvironmentVariable (lpName: PChar; lpBuffer: PChar; nSize: DWORD): DWORD; - выявляет присутствие переменной окружения lpName и записывает ее значение в lpBuffer. nSize- размер буфера. Функция возвращает кол-во скопированных символов или 0.

function SetEnvironmentVariable (lpName, lpValue: PChar): BOOL; - позволяет удалять, добавлять и модифицировать значение переменной lpName.

function GetCurrentDirectory (nBufferLength: DWORD; lpBuffer: PChar): DWORD;

function SetCurrentDirectory (lpPathName: PChar): BOOL; - получает и устанавливает текущий каталог процесса.

function GetCurrentProcess: THandle; - возвращает описатель текущего процесса

function GetCurrentProcessId: DWORD; - возвращает идентификатор текущего процесса

Завершить процесс можно тремя способами

1. Один из потоков вызывает функцию procedure ExitProcess (uExitCode: UINT); uExitCode - код возврата.

2. Поток другого процесса вызывает function TerminateProcess (hProcess: THandle; uExitCode: UINT): BOOL;

3. Все потоки процесса умирают по своей воле.

Пример:

procedure TForm1.Button2Click(Sender: TObject);

begin

if not TerminateProcess(pi.hProcess,0)

then raise Exception.Create(SysErrorMessage(GetLastError));

if not CloseHandle(pi.hProcess)

then raise Exception.Create(SysErrorMessage(GetLastError));

end;


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: