Я хочу использовать 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
больше не указывал на эту папку, чтобы я мог удалить или переименовать эту папку. Что я должен делать?
Кроме того, commandLine
уже можно записать, так зачем создавать его копию? Почему programPath
является ссылкой?
Если все, что вам нужно, это запускать другие программы, зачем писать приложение на C++?
Для демонстрации я удалил часть кода одной из своих функций, поэтому она написана так. Я хочу написать программу, похожую на Listary, но сейчас я знаю только C++, поэтому я буду использовать C++ в качестве языка разработки, и я скоро собираюсь в аспирантуру, поэтому у меня нет времени изучать новый язык. Проблема решена, спасибо за внимание
Ранее я запускал программу, используя точные пути к файлам, и обнаружил, что ее не удалось запустить из-за недостаточных разрешений, тогда как запуск с помощью cmd.exe
работал нормально, поэтому я собираюсь использовать этот метод для его запуска.
не удалось запустить из-за недостаточности прав" - Значит вы что-то сделали не так. Запускать через cmd.exe
не обязательно.
Я улучшу его, когда у меня будет время, спасибо за предложение (●'◡'ا)
Проблема в том, что вы указали NULL
в качестве рабочего каталога, поэтому рабочий каталог будет унаследован от вашей программы запуска. Если вы запускаете программу запуска из каталога, в котором она находится (например, дважды щелкнув файл в проводнике), это означает, что процесс, который вы запускаете из него, также будет иметь этот каталог в качестве рабочего каталога, поэтому будет не только дескриптор для это, но также и относительные пути будут разрешены с использованием этого каталога в качестве базового (что в некоторых случаях может быть неожиданным).
Решение состоит в том, чтобы извлечь часть пути программы, которую вы запускаете, и передать ее в качестве рабочего каталога. Итак, если вы запускаете, скажем, C:\Windows\System32\notepad.exe
, вам нужно установить его рабочий каталог на C:\Windows\System32
. (То же самое произойдет, если вы запустите программу из проводника.)
std::filesystem::path::parent_path поможет вам с этой задачей.
L"cmd.exe /c start для того, что вам нужно cmd exec ?!? exece Direct
Everything.exe
. и если у вас есть точный путь к нему - передайте его в качестве первого аргументаCreateProcessW
. начните с этого