Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Программирование для Windows NT

© Александр Фролов, Григорий Фролов
Том 26, часть 1, М.: Диалог-МИФИ, 1996, 272 стр.
Рецензия PC WEEK

[Назад] [Содеожание] [Дальше]

Запуск процесса

Пользователь запускает процесс при помощи приложений Program Manager и File Manager. Он может также воспользоваться командной строкой в системном приглашении консоли Microsoft Windows NT.

Что же касается приложения, то оно может выполнить эту задачу как при помощи уже известных вам из программирования для Microsoft Windows версии 3.1 функций WinExec XE "WinExec" и LoadModule XE "LoadModule" , так и при помощи функции CreateProcess XE "CreateProcess" , специально предназначенной для запуска процессов. Заметим, что с помощью этой функции в середе Microsoft Windows NT версии 3.51 для платформы Intel вы можете запустить как 32-разрядные, так и 16-разрядные приложения Windows, а также программы MS-DOS и 16-разрядные консольные приложения OS/2 (напомним, что первые версии операционной системы OS/2 разрабатывались совместно фирмами Microsoft и IBM).

Параметры функции CreateProcess

Функция CreateProcess имеет много параметров, однако ей не так сложно пользоваться, как это может показаться на первый взгляд:


BOOL CreateProcess(
  LPCTSTR lpApplicationName,  // указатель на имя исполняемого 
                              // модуля 
  LPTSTR  lpCommandLine,      // указатель на командную строку
  LPSECURITY_ATTRIBUTES lpProcessAttributes, // указатель на 
                        //          атрибуты защиты процесса
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // указатель на 
                        //          атрибуты защиты задачи
  BOOL bInheritHandles, // флаг наследования идентификатора 
  DWORD dwCreationFlags,// флаги создания процесса 
  LPVOID lpEnvironment, // указатель на блок среды выполнения 
  LPCTSTR lpCurrentDirectory,  // указатель на имя текущего 
                               // каталога 
  LPSTARTUPINFO lpStartupInfo, // указатель на структуру 
                               //  STARTUPINFO 
  LPPROCESS_INFORMATION lpProcessInformation); // указатель на 
                            // структуру PROCESS_INFORMATION  

Если функция CreateProcess завершается успешно, она возвращает значение TRUE. В противном случае возвращается значение FALSE. Код ошибки вы можете получить, вызвав функцию GetLastError XE "GetLastError" .

lpApplicationName

lpCommandLine

Параметры lpApplicationName и lpCommandLine используются для указания имя программного файла и параметров запуска процесса. Вы можете использовать один или оба этих параметра.

Через параметр lpApplicationName вы можете передать указатель на строку, закрытую двоичным нулем и содержащую полный либо частичный путь к программному файлу. При этом параметр lpCommandLine может иметь значение NULL либо указывать на строку параметров запуска приложения. Если это потребуется, приложение может извлечь адрес строки параметров через параметы функции WinMain, либо при помощи функции GetCommandLine, не имеющей параметров. Последняя возвращает адрес искомой строки.

Вы можете также передать через параметр lpApplicationName значение NULL, указав адрес строки пути к программному файлу через параметр lpCommandLine. В этом случае можно передать параметры процессу, добавив их в этой строке к пути файла через пробел. Таким образом, в параметре lpCommandLine можно указать адрес командной строки для запуска процесса.

lpProcessAttributes

lpThreadAttributes

Параметры lpProcessAttributes и lpThreadAttributes указывают атрибуты защиты, соответвтвенно, процесса и его главной задачи, которая получает управление при запуске процесса. В наших примерах мы будем указывать оба этих параметра как NULL, используя значения атрибутов защиты, принятые по умолчанию.

bInheritHandles

Флаг наследования идентификатора процесса и задачи bInheritHandles определяет, как это видно из названия, возможность использования данных идентификаторов в порожденных процессах и задачах. Если такая возможность вам необходима, указите для этого параметра значение TRUE. В наших приложениях мы будем указывать значение FALSE, отменяющее наследование.

dwCreationFlags

Рассмотрим теперь параметр dwCreationFlags.

Этот параметр определяет способ, которым будет запущен процесс, а также класс приоритета процесса. Соответственно, для параметра dwCreationFlags можно использовать флаги создания процесса, объединяя их между собой оператором логического ИЛИ, а также с одним из значений, определяющих класс приоритета процесса.

Флаги создания процесса перечислены ниже:

·       CREATE_SUSPENDED

Сразу после создания процесса его главная задача будет находиться в приостановленном состоянии. Работу этой задачи можно возобновить при помощи функции ResumeThread XE "ResumeThread" . Этот флаг может быть использован при отладке процесса.

·       DEBUG_PROCESS

Флаг DEBUG_PROCESS используется отладчиками, которые создают процесс для отладки. Если указан этот флаг, родительский процесс (то есть отладчик) информируется о различных событиях, возникающих в отлаживаемом процессе.

·       DEBUG_ONLY_THIS_PROCESS

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

·       CREATE_UNICODE_ENVIRONMENT

Этот флаг используется в том случае, если для блока среды процесса, адрес которого передается через параметр lpEnvironment, используется кодировка Unicode. В противном случае предполагается, что для блока среды используются символы в коде ANSI.

Рассмотрение кодировки Unicode выходит за рамки этой книги, однако мы, возможно, расскажем вам о ней в одной из следующих наших книг, посвященных операционной системе Microsoft Windows NT.

·       CREATE_NEW_CONSOLE

Используется для консольных процессов. Если указан флаг CREATE_NEW_CONSOLE, для нового процесса создается новая консоль. Консольные процессы мы не будем пока рассматривать для экономии места в книге. Этот флаг несовместим с флагом DETACHED_PROCESS.

·       DETACHED_PROCESS

Используется для консольных процессов. Если указан этот флаг, новый консольный процесс не имеет доступа к родительской консоли. При необходимости он может создать новую консоль. Этот флаг несовместим с флагом CREATE_NEW_CONSOLE.

·       CREATE_NEW_PROCESS_GROUP

Используется для консольных процессов. Новый процесс будет корневым для группы процессов.

·       CREATE_SEPARATE_WOW_VDM

Используется для запуска 16-разрядных приложоений Microsoft Windows. Если установлен флаг CREATE_SEPARATE_WOW_VDM, для работы приложения создается отдельная виртуальная машина DOS. Если произойдет ошибка в этом приложении, то она не скажется на работе остальных 16-разрядных приложений Microsoft Windows, работающих на других виртуальных машинах (так как последние находятся в другом адресном пространстве).

·       CREATE_DEFAULT_ERROR_MODE

Новый процесс не наследует режим обработки ошибок, установленный родительским процессом при помощи функции SetErrorMode, и должен устанавливать этот режим самостоятельно.

·       REALTIME_PRIORITY_CLASS

·       HIGH_PRIORITY_CLASS

·       NORMAL_PRIORITY_CLASS

·       IDLE_PRIORITY_CLASS

Приведенные выше четыре флага указывают класс приоритета нового процесса. Обычно вы должны использовать значение NORMAL_PRIORITY_CLASS XE "NORMAL_PRIORITY_CLASS" .

lpEnvironment

Наряду с регистрационной базой данных, в которой приложения могут хранить необходимые им для выполнения программы, операционная система Microsoft Windows NT сохранила такой атавизм MS-DOS, как среда выполнения программ (очевидно, сохранила для обратной совместимости с этой операционной системой). В MS-DOS переменные среды устанавливались при помощи команд в файле autoexec.bat. Операционная система Microsoft Windows NT версии 3.51 позволяет это сделать через приложение Control Panel.

Если дочерний процесс должен использовать родительский блок среды выполнения, через параметр lpEnvironment необходимо передать значение NULL.

Родительский процесс может также подготовить новый блок среды, состоящий из расположенных друг за другом символьных строк, закрытых двоичным нулем. Последняя из этих строк должна быть закрыта двумя двоичными нулями.

При необходимости процесс может получить адрес блока среды при помощи функции GetEnvironmentStrings, не имеющей параметров. Функция GetEnvironmentVariable позовляет узнать значение отдельных переменных блока среды. Описание этой функции вы найдете в SDK.

lpCurrentDirectory

Параметр lpCurrentDirectory задает путь к символьной строке, закрытой двоичным нулем, содержащей путь к каталогу, который будет использован как рабочий при запуске процесса. Если указать этот параметр как NULL, в качестве рабочего для нового процесса будет использован рабочий каталог родительского процесса.

lpStartupInfo

Через параметр lpStartupInfo вы должны передать функции CreateProcess XE "CreateProcess" указатель на структуру типа STARTUPINFO, определяющую внешний вид окна, создаваемого для процесса:


typedef struct _STARTUPINFO 
{  
  DWORD  cb;              // размер структуры в байтах
  LPTSTR lpReserved;      // зарезервировано
  LPTSTR lpDesktop;    // рабочий стол и станция для процесса
  LPTSTR lpTitle;      // заголовок окна консольного процесса
  DWORD  dwX;             // координата угла окна в пикселах
  DWORD  dwY;             // координата угла окна в пикселах
  DWORD  dwXSize;         // ширина окна в пикселах
  DWORD  dwYSize;         // высота окна в пикселах
  DWORD  dwXCountChars;   // ширина консольного окна
  DWORD  dwYCountChars;   // высота консольного окна
  DWORD  dwFillAttribute; // атрибуты текста консольного окна
  DWORD  dwFlags;         // заполненные поля структуры
  WORD   wShowWindow;     // размеры окна по умолчанию
  WORD   cbReserved2;     // зарезервировано
  LPBYTE lpReserved2;     // зарезервировано
  HANDLE hStdInput;       // консольный буфер ввода
  HANDLE hStdOutput;      // консольный буфер вывода
  HANDLE hStdError; // консольный буфер вывода сообщений 
                    // об ошибках
} STARTUPINFO, *LPSTARTUPINFO;

Несмотря на внушительный размер этой структуры, ее заполнение не вызовет у вас особых трудностей, так как большинство полей можно не использовать.

cb

Поле cb должно содержать размер структуры STARTUPINFO в байтах.

dwFlags

Поле dwFlags содержит флаги, определяющие, содержимое каких полей структуры STARTUPINFO необходимо учитывать при запуске нового процесса, а также три дополнительных флага:

 Значение

 Используемые поля

 STARTF_USESHOWWINDOW

 wShowWindow

 STARTF_USEPOSITION

 dwX, dwY

 STARTF_USESIZE

 dwXSize, dwYSize

 STARTF_USECOUNTCHARS

 dwXCountChars, dwYCountChars

 STARTF_USEFILLATTRIBUTE

 dwFillAttribute

 STARTF_USESTDHANDLES

 hStdInput, hStdOutput и hStdError

Дополнительными являются флаги STARTF_FORCEONFEEDBACK, STARTF_FORCEOFFFEEDBACK и STARTF_SCREENSAVER.

Использование первого из этих флагов приводит к тому что при запуске приложения курсор мыши принимает форму песочных часов со стрелкой. При этом пользователь может работать с другими приложениями, зная, что процесс запуска данного приложения еще не завершен. Как только приложение будет запущено и станет активным, курсор примет свою обычную форму.

Если же указан флаг STARTF_FORCEOFFFEEDBACK, в процессе запуска приложения курсор имеет обычную форму.

Флаг STARTF_SCREENSAVER используется для создания приложений, предохраняющих экран монитора от преждеверменного выгорания. Этот флаг вызывает снижение класса приоритета после запуска до IDLE_PRIORITY_CLASS XE "IDLE_PRIORITY_CLASS" , несмотря на то что при инициализации класс приоритета был NORMAL_PRIORITY_CLASS XE "NORMAL_PRIORITY_CLASS" . Если пользователь активизирует окно такого приложения, его класс приоритета автоматически повышается.

lpDesktop

Поле lpDesktop используется для выбора рабочего стола и рабочей станции, где будет запущен процесс. Если вы собираетесь использовать текущий рабочий стол и текущую рабочую станцию, укажите в этом поле значение NULL.

lpTitle

Для консольного процесса (и только для него) вы можете указать заголовок окна в поле lpTitle. Если же в этом поле задать значение NULL, для заголовка будет использовано имя файла.

dwX
dwY

Поля dwX и dwY определяют, соответственно, координаты X и Y левого верхнего угла окна графического приложения в пикселах. Эти значения используются для позиционирования главного окна приложения только в том случае, если при создании окна функцией CreateWindow расположение окна было указано как CW_USEDEFAULT XE "CW_USEDEFAULT" .

dwXSize
dwYSize

Аналогично, поля dwXSize и dwYSize определяют, соответственно, ширину и высоту окна графического приложения в пикселах. Эти значения используются в том случае, если при создании окна функцией CreateWindow размыры окна были указаны как CW_USEDEFAULT XE "CW_USEDEFAULT" .

dwXCountChars
dwYCountChars

Поля dwXCountChars и dwYCountChars задают, соответственно, ширину и высоту окна консольного приложения в символах.

dwFillAttribute

Содержимое поля dwFillAttribute задает цвет текста и фона для окна консольного приложнения.

wShowWindow

Поле wShowWindow определяет значение по умолчанию, которое будет использовано при первом вызове функции ShowWindow для главного окна приложения.

Остановимся на этом подробнее.

Как вы, наверное, помните, в приложениях Microsoft Windows версии 3.1 функция WinMain получала параметр nCmdShow, определяющий, в каком виде должно отображаться окно - в нормальном, минимизированном, максимизированном и так далее.

В среде Microsoft Windows NT параметр nCmdShow функции WinMain всегда имеет значение SW_SHOWDEFAULT XE "SW_SHOWDEFAULT" . В этом случае для определения внешнего вида главного окна прилоджения используется содержимое поля wShowWindow структуры STARTUPINFO XE "STARTUPINFO" . Здесь, а также в качестве параметров функции ShowWindow, вы можете использовать следующие значения:

 Значение

 Внешний вид окна приложения

 SW_MINIMIZE

 Минимизировано

 SW_MAXIMIZE

 Максимизировано

 SW_RESTORE

 Восстановлено в исходное состояние (это значение используется при восстановлении размеров минимизированного ранее окна)

 SW_HIDE

 Скрыто

 SW_SHOW

 Отображается с использованием текущих размеров и расположения

 SW_SHOWDEFAULT

 Отображается с использованием размеров и расположения, заданных в структуре STARTUPINFO при создании процесса функцией CreateProcess XE "CreateProcess"

 SW_SHOWMAXIMIZED

 Окно активизируется и отображается в максимизированном виде

 SW_SHOWMINIMIZED

 Окно активизируется и отображается в минимизированном виде

 SW_SHOWMINNOACTIVE

 Минимизируется, но не становится активным

 SW_SHOWNA

 Окно отображается в текущем виде, но не активизируется

 SW_SHOWNOACTIVATE

 Устанавливаются размеры и расположение окна, которые оно только что имело. Активизация окна не выполняется

 SW_SHOWNORMAL XE "SW_SHOWNORMAL"

 Окно активизируется и отображается. Минимизированное окно восстанавливается

Вернемся к полям структуры STARTUPINFO.

hStdInput
hStdOutput
hStdError

Поля hStdInput, hStdOutput и hStdError определяют идентификаторы буферов, которые используются консольными приложениями, соответственно, для ввода, вывода обычной информации и вывода сообщений об ошибках.

lpProcessInformation

Перед вызовом функции CreateProcess вы должны передать ей через параметр lpProcessInformation адрес структуры типа PROCESS_INFORMATION XE "PROCESS_INFORMATION" , в которую будут записаны идентификаторы и системные номера созданного процесса и его главной задачи:


typedef struct _PROCESS_INFORMATION
{ 
  HANDLE hProcess;    // идентификатор процесса
  HANDLE hThread;     // идентификатор главной задачи процесса
  DWORD  dwProcessId; // системный номер процесса
  DWORD  dwThreadId;  // системный номер главной задачи 
                      // процесса
} PROCESS_INFORMATION;

Пользуясь идентификаторами, полученными из полей hProcess и hThread, родительский процесс может управлять порожденным процессом и его главной задачей, например, изменяя класс приоритета процесса или относительный приоритет его главной задачи.

Важно отметить, что после использования родительский процесс обязан закрыть полученные идентификаторы порожденного процесса и задачи при помощи функции CloseHandle XE "CloseHandle" .

[Назад] [Содеожание] [Дальше]