2

Моя цель сделать так, чтобы программа начинала выполнять дальнейший код только после того, как cmd.exe выполнит команду и умрёт. Так, чтобы после смерти процесса cmd.exe программа начинала выполнять команду cout << "test" << endl;

Сам код:

#include <iostream>
#include "windows.h"
using namespace std;

int main() { ShellExecuteW(0, L"open", L"cmd.exe", L"/C pause", 0, SW_SHOW); cout << "test" << endl; }

Когда я компилирую пример от user7860670

У меня вылетает компилятор с ошибкой:
if ($?) { g++ writer.cpp -o writer } ; if ($?) { .\writer } D:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\mattc\AppData\Local\Temp\cc7ezUqJ.o:writer.cpp:(.text+0x23): undefined reference to '__imp_CoInitializeEx' D:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\mattc\AppData\Local\Temp\cc7ezUqJ.o:writer.cpp:(.text+0x17f): undefined reference to '__imp_CoUninitialize' collect2.exe: error: ld returned 1 exit status

  • #include <stdlib.h> int system(const char *command); – AlexGlebe Feb 13 '24 at 12:23
  • спасибо, но мне надо чтобы команда срабатывала в новой консоли, а не в консоли проекта – adisteyf Feb 13 '24 at 12:29
  • Используйте фунуцию ShellExecuteEx + WaitForSingleObject. – user7860670 Feb 13 '24 at 13:25
  • ShellExecuteEx заполняет дескриптор созданного процесса – user7860670 Feb 13 '24 at 14:18
  • ShellExecuteEx а не ShellExecuteW. – HolyBlackCat Feb 13 '24 at 14:47
  • Программа вылетает – adisteyf Feb 13 '24 at 15:18
  • Передавайте дескриптор процесса, а не окна. – user7860670 Feb 13 '24 at 15:50
  • передал cnsl.hProcess, но ожидание то не работает, то работает, то вылетает, как это пофиксить? – adisteyf Feb 13 '24 at 17:34
  • структуру SHELLEXECUTEINFO необходимо инициализировать нулями перед заполнением перед отправкой в функцию, а у вас в половине полей мусор. Еще перед использованием ShellExecuteEx необходимо выполнять CoInitializeEx. А результаты вызовов - проверять. Поле lpFile обычно только для имени исполняемого файла, а аргументы следует в поле параметров пихать. – user7860670 Feb 13 '24 at 18:17

4 Answers4

0

На самом деле так делать нельзя. В данном случае, ты выполняешь запуск через Shell, не имея хендла на процесс.

Ты, конечно, можешь сделать что-то типо фиксации процесса через проверку запущен ли ещё этот процесс, но если ты будешь проверять cmd.exe, то в системе таких процессов может быть несколько. В таком случае алгоритм будет не полноценным.

Для нормальной работы тебе нужно использовать WinAPI. А именно - CreateProcess. https://learn.microsoft.com/en-us/windows/win32/procthread/creating-processes

  • Так ShellExecuteW это тоже winapi. Судя по комментам, из ShellExecuteEx можно достать handle. – HolyBlackCat Feb 13 '24 at 14:00
0

Пример использования ShellExecuteExW с WaitForSingleObject:

#define WIN32_LEAN_AND_MEAN
#include <combaseapi.h>
#include <shellapi.h>
#include <Windows.h>

#include <iostream> #include <memory> #include <cstdlib>

int main() { if (not SUCCEEDED(::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED bitor COINIT_DISABLE_OLE1DDE))) { ::std::cerr << "CoInitializeEx failed" << ::std::endl; ::std::exit(EXIT_FAILURE); } { SHELLEXECUTEINFOW info { .cbSize{sizeof(info)} , .fMask{SEE_MASK_NOCLOSEPROCESS} , .lpVerb{L"open"} , .lpFile{L"cmd.exe"} , .lpParameters{L"/C pause"} , .nShow{SW_SHOW} }; if ((FALSE == ::ShellExecuteExW(::std::addressof(info))) or (not info.hProcess)) { ::std::cerr << "ShellExecuteExW failed" << ::std::endl; ::std::exit(EXIT_FAILURE); } if (WAIT_OBJECT_0 != ::WaitForSingleObject(info.hProcess, INFINITE)) { ::std::cerr << "WaitForSingleObject failed" << ::std::endl; ::std::exit(EXIT_FAILURE); } ::CloseHandle(info.hProcess); } ::CoUninitialize(); ::std::cout << "done" << ::std::endl; ::std::system("pause"); return EXIT_SUCCESS; }

user7860670
  • 29,796
0

Могу предложить решение с использованием библиотеки cstdlib:

#inclide <iostream>
#include <cstdlib>

using namespace std;

int main() { system("cd /d C:/Windows/System32 && cmd.exe"); cout << "test" << endl; }

Запускается командная строка с правами администратора, код самой программы не выполняется до закрытия командной строки командой "exit".

-2

Я так и не смог завершить проект на C++, но я сделал точно такой же проект на Rust. Rust более легче и эффективнее в этом плане, т. к. получилось все коротко и сам раст быстрее, чем C++.