У меня есть следующий код, который выполняет 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;
Вопрос отредактирован.
Проблема в том, что 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);
Пожалуйста, предоставьте минимальный воспроизводимый пример, показывающий, как вы звоните ExecAndWait(). Но почему вы вообще выполняете cmd.exe? Вместо этого вы должны выполнять powershell.exe (или любой другой .exe) напрямую. Нет смысла выполнять cmd.exe, если только вы не выполняете настоящие консольные команды, которые не реализованы как собственные .exe.