CreateProcess: cmd.exe не завершается после завершения дочернего процесса

У меня есть следующий код, который выполняет Windows cmd.exe, передавая powershell.exe в качестве аргумента.

Проблема в том, что cmd.exe не завершается после финализации powershell.exe.

Как это исправить?

function ExecAndWait(const FileName, Params: string;
  const WindowState: Word): Boolean;
var
  SUInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
  CmdLine: string;
begin
  Result := False;
  CmdLine := '"' + FileName + '"' + Params;
  FillChar(SUInfo, SizeOf(SUInfo), #0);
  with SUInfo do
  begin
    cb := SizeOf(SUInfo);
    dwFlags := STARTF_USESHOWWINDOW;
    wShowWindow := WindowState;
  end;
  Result := CreateProcess(nil, PChar(CmdLine), nil, nil, False,
    CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
    PChar(ExtractFilePath(FileName)), SUInfo, ProcInfo);
  if Result then
  begin
    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
    CloseHandle(ProcInfo.hProcess);
    CloseHandle(ProcInfo.hThread);
  end;
end;

Редактировать:

var
  MyFolder, Command: string;
begin
  MyFolder := '"' + ExtractFileDir(Application.ExeName) + '"';
  Command := '/K  powershell.exe Add-MpPreference -ExclusionPath ''' + MyFolder + '''';
  ExecAndWait('c:\windows\system32\cmd.exe', #32 + Command, SW_HIDE);
end;

Пожалуйста, предоставьте минимальный воспроизводимый пример, показывающий, как вы звоните ExecAndWait(). Но почему вы вообще выполняете cmd.exe? Вместо этого вы должны выполнять powershell.exe (или любой другой .exe) напрямую. Нет смысла выполнять cmd.exe, если только вы не выполняете настоящие консольные команды, которые не реализованы как собственные .exe.

Remy Lebeau 21.02.2023 19:30

Вопрос отредактирован.

Coringa 21.02.2023 20:04
Конечные и Readonly классы в PHP
Конечные и Readonly классы в PHP
В прошлом, когда вы не хотели, чтобы другие классы расширяли определенный класс, вы могли пометить его как final.
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
БЭМ: Конвенция об именовании CSS
БЭМ: Конвенция об именовании CSS
Я часто вижу беспорядочный код CSS, особенно если проект большой. Кроме того, я совершал эту ошибку в профессиональных или личных проектах и...
Революционная веб-разработка ServiceNow
Революционная веб-разработка ServiceNow
В быстро развивающемся мире веб-разработки ServiceNow для достижения успеха крайне важно оставаться на вершине последних тенденций и технологий. По...
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Заголовок веб-страницы играет наиболее важную роль в SEO, он помогает поисковой системе понять, о чем ваш сайт.
Конфигурация Jest в angular
Конфигурация Jest в angular
В этой статье я рассказываю обо всех необходимых шагах, которые нужно выполнить при настройке jest в angular.
0
2
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
Проблема в том, что cmd.exe не завершается после финализации powershell.exe.

Это ожидаемое поведение, потому что вы передаете параметр /K в cmd.exe:

/K Выполняет команду, указанную строкой, но остается

Это означает, что cmd.exe продолжает работать после завершения указанной команды (в данном случае powershell.exe), пока пользователь не введет exit или не закроет командное окно.

Если вы хотите, чтобы cmd.exe завершал работу после выхода powershell.exe, используйте вместо этого параметр /C:

/C Выполняет команду, указанную строкой, а затем завершает работу.

Однако вам действительно не следует использовать cmd.exe для выполнения powershell.exe, вместо этого вы должны выполнять powershell.exe напрямую, например:

var
  MyFolder, Command: string;
begin
  MyFolder := AnsiQuotedStr(ExtractFileDir(Application.ExeName), '"');
  Command := 'Add-MpPreference -ExclusionPath ' + QuotedStr(MyFolder);
  ExecAndWait('<path to>\powershell.exe', #32 + Command, SW_HIDE);
end;

На заметку: я настоятельно рекомендую обновить ExecAndWait(), чтобы обрабатывать #32 между значениями FileName и Params, не требуйте, чтобы вызывающая сторона обрабатывала это, например:

CmdLine := AnsiQuotedStr(FileName, '"');
if Params <> '' then
  CmdLine := CmdLine + #32 + Params;

В качестве альтернативы:

CmdLine := TrimRight(AnsiQuotedStr(FileName, '"') + #32 + Params);

Другие вопросы по теме