Запуск программы как процесса Windows

Создает новый процесс и его основной поток. Новый процесс выполняется в контексте безопасности вызывающего процесса.

Если вызывающий процесс олицетворяет другого пользователя, новый процесс использует маркер для вызывающего процесса, а не токен олицетворения. Чтобы запустить новый процесс в контексте безопасности пользователя, представленного маркером олицетворения, используйте функцию CreateProcessAsUser или CreateProcessWithLogonW .

Синтаксис

BOOL CreateProcessA( [in, optional] LPCSTR lpApplicationName, [in, out, optional] LPSTR lpCommandLine, [in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes, [in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes, [in] BOOL bInheritHandles, [in] DWORD dwCreationFlags, [in, optional] LPVOID lpEnvironment, [in, optional] LPCSTR lpCurrentDirectory, [in] LPSTARTUPINFOA lpStartupInfo, [out] LPPROCESS_INFORMATION lpProcessInformation );

Параметры

[in, optional] lpApplicationName

Имя выполняемого модуля. Этот модуль может быть приложением на основе Windows. Это может быть другой тип модуля (например, MS-DOS или OS/2), если соответствующая подсистема доступна на локальном компьютере.

В строке можно указать полный путь и имя файла модуля для выполнения или указать частичное имя. В случае частичного имени функция использует текущий диск и текущий каталог для завершения спецификации. Функция не будет использовать путь поиска. Этот параметр должен включать расширение имени файла; расширение по умолчанию не предполагается.

Параметр lpApplicationName может иметь значение NULL. В этом случае имя модуля должно быть первым маркером с разделителями пробелами в строке lpCommandLine . Если вы используете длинное имя файла, содержащее пробел, используйте строки в кавычках, чтобы указать, где заканчивается имя файла и начинаются аргументы; В противном случае имя файла будет неоднозначным. Например, рассмотрим строку «c:program filessub dirprogram name». Эту строку можно интерпретировать несколькими способами. Система пытается интерпретировать возможности в следующем порядке:

  1. c:program.exe
  2. c:program filessub.exe
  3. c:program filessub dirprogram.exe
  4. c:program filessub dirprogram name.exe

Если исполняемый модуль является 16-разрядным приложением, lpApplicationName должно иметь значение NULL, а строка, на которую указывает lpCommandLine , должна указывать исполняемый модуль, а также его аргументы.

Чтобы запустить пакетный файл, необходимо запустить интерпретатор команд; Задайте для параметра lpApplicationName значение cmd.exe и задайте для lpCommandLine следующие аргументы: /c плюс имя пакетного файла.

[in, out, optional] lpCommandLine

Командная строка, выполняемая.

Максимальная длина этой строки составляет 32 767 символов, включая завершающий символ NULL в Юникоде. Если lpApplicationName имеет значение NULL, часть имени модуля lpCommandLine ограничена MAX_PATH символами.

Автоматический запуск приложений с помощью папки Автозагрузка в ОС Windows

Версия этой функции в Юникоде CreateProcessW может изменять содержимое этой строки. Поэтому этот параметр не может быть указателем на память, доступную только для чтения (например, переменную const или строку литерала). Если этот параметр является строкой константы, функция может привести к нарушению доступа.

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

Если и lpApplicationName , и lpCommandLine имеют значение, отличное от NULL, строка, завершающаяся значением NULL, на которую указывает lpApplicationName , указывает модуль для выполнения, а строка, завершающаяся значением NULL, на которую указывает lpCommandLine , указывает командную строку. Новый процесс может использовать GetCommandLine для получения всей командной строки. Консольные процессы, написанные на языке C, могут использовать аргументы argc и argv для анализа командной строки. Так как argv[0] — это имя модуля, программисты C обычно повторяют имя модуля в качестве первого маркера в командной строке.

Если lpApplicationName имеет значение NULL, первый маркер командной строки с разделителями пробелами указывает имя модуля. Если вы используете длинное имя файла, содержащее пробел, используйте строки в кавычках, чтобы указать, где заканчивается имя файла и начинаются аргументы (см. описание параметра lpApplicationName ). Если имя файла не содержит расширения, добавляется .exe. Поэтому, если расширение имени файла — .com, этот параметр должен включать расширение .com. Если имя файла заканчивается точкой (.) без расширения или если имя файла содержит путь, .exe не добавляется. Если имя файла не содержит пути к каталогу, система выполняет поиск исполняемого файла в следующей последовательности:

  1. Каталог, из которого загружено приложение.
  2. Текущий каталог для родительского процесса.
  3. 32-разрядный системный каталог Windows. Используйте функцию GetSystemDirectory , чтобы получить путь к этому каталогу.
  4. 16-разрядный системный каталог Windows. Нет функции, которая получает путь к этому каталогу, но выполняется поиск. Имя этого каталога — System.
  5. Каталог Windows. Используйте функцию GetWindowsDirectory , чтобы получить путь к этому каталогу.
  6. Каталоги, перечисленные в переменной среды PATH. Обратите внимание, что эта функция не выполняет поиск по пути для каждого приложения, указанному в разделе реестра Пути приложений . Чтобы включить этот путь для каждого приложения в последовательность поиска, используйте функцию ShellExecute .

[in, optional] lpProcessAttributes

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

Элемент lpSecurityDescriptor структуры задает дескриптор безопасности для нового процесса. Если lpProcessAttributes имеет значение NULL или lpSecurityDescriptor имеет значение NULL, процесс получает дескриптор безопасности по умолчанию. Списки управления доступом в дескрипторе безопасности по умолчанию для процесса поступают из основного маркера создателя. Windows XP: Списки управления доступом в дескрипторе безопасности по умолчанию для процесса поступают из основного маркера или маркера олицетворения создателя. Это поведение изменилось в Windows XP с пакетом обновления 2 (SP2) и Windows Server 2003.

Читайте также:
Как почистить компьютер от мусора для ускорения работы Windows 10 без программ самому

[in, optional] lpThreadAttributes

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

Элемент lpSecurityDescriptor структуры задает дескриптор безопасности для основного потока. Если lpThreadAttributes имеет значение NULL или lpSecurityDescriptor имеет значение NULL, поток получает дескриптор безопасности по умолчанию. Списки управления доступом в дескрипторе безопасности по умолчанию для потока поступают из маркера процесса. Windows XP: Списки управления доступом в дескрипторе безопасности по умолчанию для потока поступают из основного маркера или маркера олицетворения создателя. Это поведение изменилось в Windows XP с пакетом обновления 2 (SP2) и Windows Server 2003.

Если этот параметр имеет значение TRUE, каждый наследуемый дескриптор в вызывающем процессе наследуется новым процессом. Если параметр имеет значение FALSE, дескрипторы не наследуются. Обратите внимание, что унаследованные дескрипторы имеют те же значения и права доступа, что и исходные дескрипторы. Дополнительные сведения о наследуемых дескрипторах см. в разделе Примечания.

Службы терминалов: Нельзя наследовать дескрипторы между сеансами. Кроме того, если этот параметр имеет значение TRUE, процесс необходимо создать в том же сеансе, что и вызывающий объект.

Процессы Защищенного процесса Light (PPL): Наследование универсального дескриптора блокируется, когда процесс PPL создает процесс, отличный от PPL, так как PROCESS_DUP_HANDLE не допускается из процесса, отличного от PPL, к процессу PPL. См. раздел Управление правами на доступ и безопасность процесса.

Флаги, управляющие классом приоритета и созданием процесса. Список значений см. в разделе Флаги создания процесса.

Этот параметр также управляет классом приоритета нового процесса, который используется для определения приоритетов планирования потоков процесса. Список значений см. в разделе GetPriorityClass. Если ни один из флагов класса приоритета не указан, класс приоритета по умолчанию NORMAL_PRIORITY_CLASS , если только класс приоритета процесса создания не IDLE_PRIORITY_CLASS или BELOW_NORMAL_PRIORITY_CLASS. В этом случае дочерний процесс получает класс приоритета по умолчанию вызывающего процесса.

Если параметр dwCreationFlags имеет значение 0:

  • Процесс наследует режим ошибок вызывающего объекта и родительской консоли.
  • Предполагается, что блок среды для нового процесса содержит символы ANSI (дополнительные сведения см. в разделе параметр lpEnvironment ).
  • 16-разрядное приложение windows выполняется на общей виртуальной машине DOS (VDM).

[in, optional] lpEnvironment

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

Блок среды состоит из блока строк, завершаемых значением NULL. Каждая строка имеет следующий вид:

Имя=value

Так как знак равенства используется в качестве разделителя, его нельзя использовать в имени переменной среды.

Блок среды может содержать символы Юникода или ANSI. Если блок среды, на который указывает lpEnvironment , содержит символы Юникода, убедитесь, что dwCreationFlags содержит CREATE_UNICODE_ENVIRONMENT.

Версия ANSI этой функции CreateProcessA завершается сбоем, если общий размер блока среды для процесса превышает 32 767 символов.

Обратите внимание, что блок среды ANSI завершается двумя нулевыми байтами: один для последней строки, еще один для завершения блока. Блок среды Юникода завершается четырьмя нулевыми байтами: два для последней строки, еще два для завершения блока.

[in, optional] lpCurrentDirectory

Полный путь к текущему каталогу для процесса. В строке также можно указать UNC-путь.

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

Чтобы задать расширенные атрибуты, используйте структуру STARTUPINFOEX и укажите EXTENDED_STARTUPINFO_PRESENT в параметре dwCreationFlags .

Дескрипторы в STARTUPINFO или STARTUPINFOEX должны быть закрыты с помощью CloseHandle , если они больше не нужны.

Важно Вызывающий объект отвечает за то, чтобы стандартные поля дескрипторов в STARTUPINFO содержали допустимые значения дескрипторов. Эти поля копируются без изменений в дочерний процесс без проверки, даже если член dwFlags указывает STARTF_USESTDHANDLES. Неправильные значения могут привести к неправильному поведению дочернего процесса или аварийному завершению. Используйте средство проверки среды выполнения Проверки приложений для обнаружения недопустимых дескрипторов.

Указатель на структуру PROCESS_INFORMATION , получающую идентификационные сведения о новом процессе.

Маркеры в PROCESS_INFORMATION должны быть закрыты с помощью CloseHandle , если они больше не нужны.

Возвращаемое значение

Если функция выполняется успешно, возвращается ненулевое значение.

Если функция выполняется неудачно, возвращается нулевое значение. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.

Обратите внимание, что функция возвращается до завершения инициализации процесса. Если не удается найти необходимую библиотеку DLL или не удается инициализировать, процесс завершается. Чтобы получить состояние завершения процесса, вызовите Метод GetExitCodeProcess.

Комментарии

Процессу назначается идентификатор процесса. Идентификатор действителен до завершения процесса. Его можно использовать для идентификации процесса или указать в функции OpenProcess , чтобы открыть дескриптор процесса. Начальному потоку в процессе также назначается идентификатор потока. Его можно указать в функции OpenThread , чтобы открыть дескриптор потока.

Идентификатор действителен до завершения потока и может использоваться для уникальной идентификации потока в системе. Эти идентификаторы возвращаются в структуре PROCESS_INFORMATION .

Имя исполняемого файла в командной строке, которое операционная система предоставляет процессу, не обязательно совпадает с именем в командной строке, которую вызывающий процесс присваивает функции CreateProcess . Операционная система может добавить полный путь к имени исполняемого файла, которое предоставляется без полного пути.

Читайте также:
Как запустить программу в скрытом режиме на Windows 7

Вызывающий поток может использовать функцию WaitForInputIdle , чтобы дождаться завершения инициализации нового процесса и ожидать ввода данных пользователем без ожидания ввода. Это может быть полезно для синхронизации между родительским и дочерним процессами, так как CreateProcess возвращает, не дожидаясь завершения инициализации нового процесса. Например, процесс создания будет использовать WaitForInputIdle перед попыткой найти окно, связанное с новым процессом.

Предпочтительным способом завершения процесса является использование функции ExitProcess , так как эта функция отправляет уведомление о приближении завершения во все библиотеки DLL, присоединенные к процессу. Другие средства завершения процесса не уведомляют подключенные библиотеки DLL. Обратите внимание, что, когда поток вызывает ExitProcess, другие потоки процесса завершаются без возможности выполнить какой-либо дополнительный код (включая код завершения потока присоединенных библиотек DLL). Дополнительные сведения см. в разделе Завершение процесса.

Родительский процесс может напрямую изменять переменные среды дочернего процесса во время создания процесса. Это единственная ситуация, когда процесс может напрямую изменить параметры среды другого процесса. Дополнительные сведения см. в разделе Изменение переменных среды.

Если приложение предоставляет блок среды, сведения о текущем каталоге системных дисков не распространяются автоматически в новый процесс. Например, существует переменная среды с именем =C: значением является текущий каталог на диске C. Приложение должно вручную передать сведения о текущем каталоге в новый процесс. Для этого приложение должно явно создать эти строки переменных среды, отсортировать их по алфавиту (так как система использует отсортированную среду) и поместить их в блок среды. Как правило, они выполняются в передней части блока среды из-за порядка сортировки блоков среды.

Один из способов получить сведения о текущем каталоге для диска X — выполнить следующий вызов: GetFullPathName(«X:», . ) . Это позволяет избежать необходимости сканирования блока среды для приложения. Если возвращается полный путь X:, нет необходимости передавать это значение в качестве данных среды, так как корневой каталог является текущим каталогом по умолчанию для диска X нового процесса.

При создании процесса с указанным CREATE_NEW_PROCESS_GROUP выполняется неявный вызов SetConsoleCtrlHandler(NULL,TRUE) от имени нового процесса; это означает, что для нового процесса отключено сочетание клавиш CTRL+C. Это позволяет оболочкам самостоятельно обрабатывать клавиши CTRL+C и выборочно передавать этот сигнал в вложенные процессы. СОЧЕТАНИЕ КЛАВИШ CTRL+BREAK не отключено и может использоваться для прерывания процесса или группы процессов.

По умолчанию передача TRUE в качестве значения параметра bInheritHandles приводит к тому, что новый процесс наследует все наследуемые дескрипторы. Это может быть проблемой для приложений, которые создают процессы из нескольких потоков одновременно, но хотят, чтобы каждый процесс наследовал разные дескрипторы. Приложения могут использовать функцию UpdateProcThreadAttributeList с параметром PROC_THREAD_ATTRIBUTE_HANDLE_LIST для предоставления списка дескрипторов, наследуемых определенным процессом.

Замечания по безопасности

Первый параметр lpApplicationName может иметь значение NULL. В этом случае имя исполняемого файла должно находиться в строке с разделителями пробелами, на которую указывает lpCommandLine. Если в имени исполняемого файла или пути есть пробел, существует риск запуска другого исполняемого файла из-за того, как функция анализирует пробелы. Следующий пример опасен тем, что функция будет пытаться выполнить «Program.exe», если она существует, а не «MyApp.exe».

LPTSTR szCmdline = _tcsdup(TEXT(«C:\Program Files\MyApp -L -S»)); CreateProcess(NULL, szCmdline, /* . */);

Если злоумышленник создает приложение с именем «Program.exe» в системе, любая программа, которая неправильно вызывает CreateProcess с помощью каталога Program Files, будет запускать это приложение вместо предполагаемого приложения.

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

LPTSTR szCmdline[] = _tcsdup(TEXT(«»C:\Program Files\MyApp» -L -S»)); CreateProcess(NULL, szCmdline, /*. */);

Примеры

Требования

Минимальная версия клиента Windows XP [| классических приложений Приложения UWP]
Минимальная версия сервера Windows Server 2003 [классические приложения | Приложения UWP]
Целевая платформа Windows
Header processthreadsapi.h (включая Windows.h в Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 Windows Server 2008 R2)
Библиотека Kernel32.lib
DLL Kernel32.dll

Источник: learn.microsoft.com

Как я могу запустить программу EXE из службы Windows, используя C #?

Это никогда не будет работать, по крайней мере, не под Windows Vista или более поздней версией. Основная проблема заключается в том, что вы пытаетесь выполнить это из службы Windows, а не в стандартном приложении Windows. Код, который вы показали, отлично работает в приложении Windows Forms, WPF или Console, но он вообще не работает в службе Windows.

Службы Windows не могут запускать дополнительные приложения, поскольку они не работают в контексте какого-либо конкретного пользователя. В отличие от обычных приложений Windows, службы теперь запускаются в изолированном сеансе и им запрещено взаимодействовать с пользователем или рабочим столом. Это не оставляет места для запуска приложения.

Дополнительная информация доступна в ответах на эти связанные вопросы:

  • Как служба Windows может запустить процесс при создании события Timer?
  • какой процесс в Windows является специфичным для пользователя?
  • служба Windows (разрешить взаимодействие с рабочим столом)

Лучшее решение вашей проблемы, как вы, вероятно, уже выяснили, состоит в том, чтобы создать стандартное приложение Windows вместо службы. Они предназначены для работы конкретного пользователя и связаны с этим рабочим столом пользователя. Таким образом, вы можете запускать дополнительные приложения, когда захотите, используя код, который вы уже указали.

Читайте также:
Убрать слежку Windows 10 программа

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

Cody Gray 15 март 2011, в 06:17
Поделиться

Основываясь на названии EXE, я собираюсь догадаться, что он пытается запустить консольное приложение и, следовательно, не ожидает взаимодействия с ним — поэтому нет проблем с запуском его из службы.

Gabe 15 март 2011, в 06:03
Cody Gray♦ 15 март 2011, в 06:04
Спасибо за ваш ответ, но что, если я назову файл bat и это не проблема.
xoops 15 март 2011, в 06:08

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

Gabe 15 март 2011, в 06:08
Cody Gray♦ 15 март 2011, в 06:09
Cody Gray♦ 15 март 2011, в 06:11
извините, я имею в виду, если я пытаюсь загрузить файл, не имеет значения.
xoops 15 март 2011, в 06:12
Cody Gray♦ 15 март 2011, в 06:13
xoops 15 март 2011, в 06:14

ооо. Благодарю. Еще один вопрос, что я могу назвать exe-файл из bat-файла, где bat-файл запускается из оконной службы. Имеет ли это смысл. Спасибо

xoops 15 март 2011, в 06:17
Cody Gray♦ 15 март 2011, в 06:21
Wojtek Turowicz 15 март 2011, в 08:56
Cody Gray♦ 15 март 2011, в 09:13
Elshan 24 нояб. 2015, в 08:27

Показать ещё 12 комментариев

Я пробовал эту статью Code Project, он отлично работает для меня. Я тоже использовал код. статья превосходна в объяснении с снимком экрана.

Я добавляю необходимое объяснение этому сценарию

Изображение 120306

Вы только что загрузили свой компьютер и собираетесь войти в систему. При входе в систему система назначает вам уникальный идентификатор сеанса. В Windows Vista первому пользователю, который должен войти на компьютер, присваивается идентификатор сеанса 1 ОС. Следующему пользователю для входа в систему будет присвоен идентификатор сеанса 2. И так далее и т.д. Вы можете просмотреть идентификатор сеанса, назначенный каждому зарегистрированному пользователю на вкладке «Пользователи» в диспетчере задач.

Но ваша служба Windows подпадает под идентификатор сеанса 0. Этот сеанс изолирован от других сеансов. Это в конечном итоге не позволяет службе Windows вызывать приложение, запущенное под пользовательским сеансом, например 1 или 2.

Изображение 120307

Чтобы вызвать приложение из службы Windows, вам необходимо скопировать элемент управления из winlogon.exe, который действует как текущий зарегистрированный пользователь, как показано ниже на снимке экрана.

Источник: overcoder.net

Запуск exe отдельно от родительского процесса

рисунок

Функция создаёт дочерний процесс как на рисунке можно ли как то запустить notepad.exe отдельно от родительского процесса?

Отслеживать
23k 1 1 золотой знак 18 18 серебряных знаков 37 37 бронзовых знаков
задан 20 июл 2019 в 5:38
Дмитрий Мизантропович Дмитрий Мизантропович
541 3 3 серебряных знака 13 13 бронзовых знаков

если кратко, в windows нет «дочерних» — «родительских» процессов как таковых. некоторые утилиты смотрят на аттрибут InheritedFromUniqueProcessId , но это ни на что не влияет, подробности: stackoverflow.com/questions/13947107/…

20 июл 2019 в 9:08
20 июл 2019 в 22:06
Посмотрите в сторону функции ShellExecute
22 июл 2019 в 13:13

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Флаг DETACHED_PROCESS означает лишь одно — что создаваемый процесс будет иметь отдельную консоль. Если процесс не консольный, он не будет иметь вообще никакого эффекта. Windows все равно пометит, что процесс был создан вашей программой.

Утилиты, которые строят дерево процессов на основе информации, возвращаемой функциями Tool Help API Process32First / Process32Next в поле th32ParentProcessID структуры PROCESSENTRY32 будут считать его дочерним. Если пользователь нажмет в диспетчере задач для вашей программы «Завершить дерево процессов», созданный процесс будет также завершен. С этим не надо бороться, это сделано специально, чтобы в ситуациях, когда программа из-за бага плодит много процессов без видимых окон и зависает, можно было решить проблему и завершить все эти процессы.

Тем не менее, создать полностью независимый процесс, который не завершается по нажатии «Завершить дерево процессов», возможно. Для этого можно использовать, например, system(«start notepad.exe»); . Команда start запускает notepad и сразу возвращает управление, командный интерпретатор закрывается. Тогда в дереве процессов с точки зрения Windows родительским процессом notepad.exe будет уже не существующий процесс командного интерпретатора; соответственно, дерево разорвано и связи с вашей программой нет.

Отслеживать
ответ дан 24 июл 2019 в 10:08
MSDN.WhiteKnight MSDN.WhiteKnight
20.1k 6 6 золотых знаков 37 37 серебряных знаков 81 81 бронзовый знак
могу ли я поменять InheritedFromUniqueProcessId у процесса в PROCESS_BASIC_INFORMATION?
24 июл 2019 в 23:57
25 июл 2019 в 3:18

NTSTATUS ntStatus = NtQueryInformationProcess(hProcess, ProcessBasicInformation, ulRetLength); получит структуру PROCESS_BASIC_INFORMATION в ней есть поле InheritedFromUniqueProcessId

Источник: ru.stackoverflow.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru