Дескрипторы некоторых программ не отсоединяются должным образом при запуске с помощью функции CreateProcess в Windows

Я хочу использовать Windows API для запуска других программ (.exe, .url, .lnk) на своем компьютере, поэтому для этого я использую следующее:

int main() {
    //const std::wstring& programPath = L"C:\\Users\\ghost\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Steam\\Steam.lnk";
    const std::wstring& programPath = L"C:\\Program Files\\Everything\\Everything.exe";

    // Prepare the command line to run the program using cmd.exe
    std::wstring commandLine = L"cmd.exe /c start \"\" \"" + programPath + L"\"";

    // Log the command line to ensure it is correct
    qDebug() << "Attempting to run command: " << commandLine;

    // Prepare the STARTUPINFO structure
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // Create a writable copy of the command line
    std::vector<wchar_t> commandLineBuffer(commandLine.begin(), commandLine.end());
    commandLineBuffer.push_back(0);

    // Create the process
    if (!CreateProcess(
            NULL,           // Module name (use command line directly)
            commandLineBuffer.data(), // Command line
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            CREATE_NO_WINDOW | DETACHED_PROCESS, // No console window, detached process
            NULL,           // Use parent's environment block
            NULL,           // Use parent's starting directory
            &si,            // Pointer to STARTUPINFO structure
            &pi)            // Pointer to PROCESS_INFORMATION structure
        ) {
        qDebug() << "Failed to create process. Error: " << GetLastError();
    } else {
        // Close process and thread handles to ensure they are completely detached
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        qDebug() << "Process created successfully: " << commandLine;
    }

    int t;
    std::cin >> t;

    return 0;
}

Запуск файлов .url и .lnk с помощью этого кода работает нормально.

Но когда я хочу использовать этот код для запуска файла .exe, я обнаружил, что папка, в которой находится приложение, по-прежнему выдает сообщение «Эта папка используется», когда приложение завершает работу. Поэтому я воспользовался Монитором ресурсов, чтобы выяснить, что дескриптор приложения, запущенного с этим кодом, все еще указывает на эту папку, что делает невозможным переименование папки.

Я запустил программу everything.exe, используя приведенный выше код, и вижу, что дескриптор everything.exe все еще указывает на эту папку, поэтому, когда я завершаю запуск этой программы, я все еще не могу удалить и переименовать эту папку. Как вы можете видеть на картинке ниже:

Я также пробовал разделить с помощью ShellExecute и разделить с помощью ShellExecuteEx, но ни то, ни другое не помогло.

Теперь я хочу, чтобы дескриптор everything.exe больше не указывал на эту папку, чтобы я мог удалить или переименовать эту папку. Что я должен делать?

L"cmd.exe /c start для того, что вам нужно cmd exec ?!? exece Direct Everything.exe. и если у вас есть точный путь к нему - передайте его в качестве первого аргумента CreateProcessW. начните с этого

RbMm 16.06.2024 11:35

Кроме того, commandLine уже можно записать, так зачем создавать его копию? Почему programPath является ссылкой?

Ted Lyngmo 16.06.2024 11:45

Если все, что вам нужно, это запускать другие программы, зачем писать приложение на C++?

Pepijn Kramer 16.06.2024 11:46

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

ghost_him 16.06.2024 12:30

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

ghost_him 16.06.2024 12:37

не удалось запустить из-за недостаточности прав" - Значит вы что-то сделали не так. Запускать через cmd.exe не обязательно.

Ted Lyngmo 16.06.2024 12:49

Я улучшу его, когда у меня будет время, спасибо за предложение (●'◡'ا)

ghost_him 17.06.2024 10:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Решение состоит в том, чтобы извлечь часть пути программы, которую вы запускаете, и передать ее в качестве рабочего каталога. Итак, если вы запускаете, скажем, C:\Windows\System32\notepad.exe, вам нужно установить его рабочий каталог на C:\Windows\System32. (То же самое произойдет, если вы запустите программу из проводника.)

std::filesystem::path::parent_path поможет вам с этой задачей.

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