Для запуска приложений из программы можно использовать следующие функции API Windows:
- ShellExecute - запускает оболочку, ассоциированную с расширением файла, передаваемого ей в качестве параметра. Например, если передать файл с расширением doc, то запустится редактор MS Word (если он установлен в системе). В качестве параметра функции можно передать и файл с раширением exe.;
- CreateProcess - создает новый процесс и его первичный поток. Данная функция используется в Win32 для запуска других приложений.;
- WinExec , LoadModule - достались в наследство от Windows 3.x, Microsoft не рекомендует использовать ее в приложениях Win32 (они работают через вызов CreateProcess).
Функция ShellExecute
ShellExecute( hwnd: THandle, // указатель на родительское окно lpOperation: PChar, //выполняемая операция lpFile: PChar, // файл или папка lpParameters: PСhar, //строка параметров запускаемой программы lpDirectory: PChar, // директория по умолчанию nShowCmd: integer // состояние окна запущенной программы );
hwnd Определяет родительское окно, которое будет получать сообщения от запускаемого приложения (например, об ошибке при запуске).
lpOperation Определяет выполняемую оперерацию. "open" - открывает файл lpFile. Файл может быть документом, приложением или папкой. "print" - печатает файл lpFile. Файл должен быть документом. Если передано приложение, то выполняются действия, аналогичные "open". "explore" - открывает папку lpFile в проводнике Windows. nil - аналогично "open".
lpFile Файл или папка. Функция может открыть или напечатать файл, открыть папку, запустить приложение.
lpParameters Если lpFile - приложение, то lpParametrs может содержать строку параметров приложения. Если lpFile - документ или папка, lpParameters должен быть nil.
nShowCmd Определяет как должно выглядеть окно запущенного приложения, приведу несколько основных констант, остальные можно посмотреть в Windows SDK.
|
Константа |
Описание |
| SW_HIDE |
Скрывает окно. |
| SW_MAXIMIZE |
Разворачивает окно. |
| SW_MINIMIZE |
Сворачивает окно. |
| SW_SHOWMAXIMIZED |
Активизирует и разворачивает окно. |
| SW_SHOWMINIMIZED |
Активизирует и сворачивает окно. |
| SW_SHOWNORMAL |
Активизирует и показывает окно в состоянии, определяемым самим приложением. |
Примеры использования функции.
Открытие файлов через OpenDialog: procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then ShellExecute(Self.Handle, 'open', PChar(OpenDialog1.FileName), nil, nil, SW_SHOWNORMAL); end;
Открытие IE с заданным URL: ShellExecute(Self.Handle, 'open', 'http://www.delphi.hostmos.ru', nil, nil, SW_SHOWMAXIMIZED);
Запуск почтового клиента: ShellExecute(Self.Handle, 'open', 'mailto:vasya@mail.ru', nil, nil, SW_SHOWNORMAL);
Примечание. Для использования ShellExecute в раздел uses надо добавить модуль ShellAPI.
Функция CreateProcess
По сравнению с ShellExecute, функция дает дополнительные возможности по управлению процессом: можно установить начальный приоритет первого потока процесса, выставить положение и размер окна приложения, дождаться завершения процесса, завершить процесс.
CreateProcess (lpApplicationName: PChar, // имя исполняемого модуля lpCommandLine: PChar, // строка параметров запускаемой программы lpProcessAttributes: TSecurityAttributes, // структура SECURITY_ATTRIBUTES процесса lpThreadAttributes: TSecurityAttributes, // структура SECURITY_ATTRIBUTES потока bInheritHandles: LongBool, // флаг наследования текущего процесса dwCreationFlags: Longword, // флаги способов создания процесса lpEnvironment: Pointer, // указатель на блок среды lpCurrentDirectory: PChar, // текущий диск и каталог lpStartupInfo:TStartupInfo, // структура STARTUPINFO lpProcessInformation: TProcessInformation // структура PROCESS_INFORMATION ): LongBool;
Приведу краткое описание функции, за более полным обращайтесь в Windows SDK.
lpApplicationName Полный путь к исполняемому модулю программы, например, c:Program FilesBorlandDelphi7BinDelphi32.exe (поиск производится только в текущей директории!). lpApplicationName может быть nil, тогда lpCommandLine должна содержать имя исполняемого модуля (если имя содержит пробелы, то оно должно быть заключено в "двойные кавычки"), отделенное от остальной строки пробелом. Если запускается 16-разрядное приложение в среде Windows NT, lpApplicationName должна быть nil, а lpCommandLine содержать имя модуля.
lpCommandLine Строка параметров, может быть nil. Если приложение указано в lpCommandLine, то поиск производится в текущей, системной и описанных в переменной окружения PATH директориях. Если приложение указано в lpApplicationName, строка параметров должна начинаться с пробела.
lpProcessAttributes Атрибуты защиты для нового процесса. Если указать nil то система сделает это по умолчанию. В Windows 9.x, Me игнорируется.
lpThreadAttributes Атрибуты защиты для первого потока созданного приложением. nil - установка по умолчанию. В Windows 9.x, Me игнорируется.
bInheritHandles Флаг наследования от процесса производящего запуск. Унаследованные дескрипторы имеют те же значения и права доступа, что и оригиналы. Наследуются если установлено в true.
dwCreationFlags Флаг способа создания процесса и его приоритет:
|
Флаг |
Описание |
| CREATE_DEFAULT_ERROR_MODE |
Новый процесс не наследует режим ошибок (error mode) вызывающего процесса. |
| CREATE_NEW_CONSOLE |
Новый процесс получает новую консоль вместо того, чтобы унаследовать родительскую. |
| CREATE_SUSPENDED |
Первичная нить процесса создается в спящем (suspended) состоянии и не выполняется до вызова функции ResumeThread. |
| HIGH_PRIORITY_CLASS |
Высокий приоритет |
| IDLE_PRIORITY_CLASS |
Поток выполняется только при простое системы |
| NORMAL_PRIORITY_CLASS |
Приоритет по умолчанию |
| REALTIME_PRIORITY_CLASS |
Наивысший приоритет |
lpEnvironment Блок среды. Если nil, то будет использован блок среды родительского процесса. Блок среды это список переменных имя=значение в виде строк с нулевым окончанием.
lpCurrentDirectory Текущий диск и каталог. Если nil, то будет использован диск и каталог процесса родителя.
lpStartupInfo Используется для настройки свойств процесса, например расположения окон и заголовок..
TStartUpInfo = record cb: Longword; lpReserved: PChar; lpDesktop: PChar; lpTitle: PChar; dwX: Longword; dwY: Longword; dwXSize: Longword; dwYSize: Longword; dwXCountChars: Longword; dwYCountChars: Longword; dwFillAttribute: Longword; dwFlags: Longword; wShowWindow: Word; cbReserved2: Word; lpReserved2: PByte; hStdInput: THandle; hStdOutput: THandle; hStdError: THandle; end;
Некоторые элементы имеют смысл, только если дочернее приложение создает перекрываемое (overlapped) окно, а другие — если это приложение осуществляет ввод-вывод на консоль. Рассмотрим только первый тип параметров.
|
Элемент |
Описание |
| cb |
Содержит количество байтов, занимаемых структу рой TStartUpInfo. Обязательно для заполнения. Инициализируйте как SizeOf(TStartUpInfo). |
lpReserved
|
Зарезервирован. Инициализируйте как nil |
| IpDesktop |
Идентифицирует имя рабочего стола, на котором запускается приложение. |
dwX dwY |
Координаты окна в пикселях. |
dwXSize dwYSize |
Определяют ширину и высоту (в пикселях) окна приложения. |
| dwFlags |
Содержит набор флагов, позволяющих управлять созданием дочернего процесса |
| wSbowWtndow |
Определяет как должно выглядеть окно запущенного приложения. В этот элемент можно записать любой из идентификаторов типа SW_* |
| cbReserved2 |
Зарезервирован. Инициализируйте как 0. |
| lpReserved2 |
Зарезервирован. Инициализируйте как nil. |
Список допустимых флагов dwFlags:
|
Флаг |
Описание |
| STARTF_USESIZE |
Заставляет использовать элементы dvXSize и dwYSize |
| STARTF_USESHOWWINDOW |
Заставляет использовать элемент wShowWindow |
| STARTF_USEPOSITION |
Заставляет использовать элементы dwX и dwY |
STARTF_FORCEONFEEDBACK STARTF_FORCEOFFFEEDBACK |
Форма курсора при запуске (с "часиками" или без) |
lpProcessInformation Информация о созданном процессе. Инициализируется самой функцией.
TProcessInformation = record hProcess: THandle; // дескриптор процесса hThread: THandle; // дескриптор первого потока процесса dwProcessId: Longword; // глобальный идентификатор процесса dwThreadId: Longword; // глобальный идентификатор потока end;
Указатели hProcess и hThread должны быть закрыты в родительском процессе функцией CloseHandle иначе произойдет утечка памяти. CloseHandle не закрывает процесс (поток), а только уменьшает счетчики открытых дескрипторов.
При удачном вызове CreateProcess возвращает true.
Если приложение Win32, то после создания процесса желательно дождаться завершения его инициализации функцией WaitForInputIdle.
Примеры использования функции.
uses Windows; ... var Rlst: LongBool; StartUpInfo: TStartUpInfo; ProcessInfo: TProcessInformation; Error: integer; begin FillChar(StartUpInfo, SizeOf(TStartUpInfo), 0); with StartUpInfo do begin cb := SizeOf(TStartUpInfo); dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK; wShowWindow := SW_SHOWNORMAL; end; Rlst := CreateProcess('C:WindowsSystem32
otepad.exe', ' c:
eadme.txt', nil, nil, false, NORMAL_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo); if Rlst then with ProcessInfo do begin WaitForInputIdle(hProcess, INFINITE); // ждем завершения инициализации CloseHandle(hThread); // закрываем дескриптор процесса CloseHandle(hProcess); // закрываем дескриптор потока end else Error := GetLastError; end;
Эквивалентный вызов функции: Rlst := CreateProcess(nil, 'notepad c:
eadme.txt', nil, nil, false, NORMAL_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo);
Можно дождаться завершения запущенного процесса и получить код его завершения. Но в этом случае работа потока, который запустил процесс, приостанавливается:
var Rlst: LongBool; StartUpInfo: TStartUpInfo; ProcessInfo: TProcessInformation; Error: integer; ExitCode: Cardinal; begin FillChar(StartUpInfo, SizeOf(TStartUpInfo), 0); with StartUpInfo do begin cb := SizeOf(TStartUpInfo); dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK; wShowWindow := SW_SHOWNORMAL; end; Rlst := CreateProcess('C:WindowsSystem32
otepad.exe', ' c:
eadme.txt', nil, nil, false, NORMAL_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo); if Rlst then with ProcessInfo do begin WaitForInputIdle(hProcess, INFINITE); // ждем завершения инициализации WaitforSingleObject(ProcessInfo.hProcess, INFINITE); // ждем завершения процесса GetExitCodeProcess(ProcessInfo.hProcess, ExitCode); // получаем код завершения CloseHandle(hThread); // закрываем дескриптор процесса CloseHandle(hProcess); // закрываем дескриптор потока end else Error := GetLastError; end;
Для принудительного завершения запущенного процесса надо вызвать функцию TerminateProcess (до вызова функции CloseHandle).
... WaitForInputIdle(hProcess, INFINITE); // ждем завершения инициализации Sleep(2000); TerminateProcess(hProcess, NO_ERROR); CloseHandle(hThread); // закрываем дескриптор процесса CloseHandle(hProcess); // закрываем дескриптор потока ...
Рамиль Мурзин
Источник www.delphi.hostmos.ru
|