代码之家  ›  专栏  ›  技术社区  ›  ghost_him

在Windows中使用CreateProcess函数启动时,某些程序的句柄未正确分离

  •  1
  • ghost_him  · 技术社区  · 2 年前

    我想使用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文件时,我发现应用程序所在的文件夹在应用程序运行结束时仍然提示“this folder is use”,所以我用资源监视器发现用这个代码运行的应用程序的句柄仍然指向这个文件夹,这导致了下面的问题。所以我使用资源监视器发现,用程序启动的应用程序句柄仍然指向该文件夹,这使得无法重命名文件夹。

    我用上面的代码启动了everything.exe程序,我可以看到everything.exe的句柄仍然指向这个文件夹,所以当我运行完这个程序时,我仍然无法删除和重命名这个文件夹。如下图所示:

    enter image description here

    我还尝试过使用ShellExecute进行分离和使用ShellExecuteEx进行分离,两者都不起作用

    现在我希望everything.exe的句柄不再指向此文件夹,以确保我可以删除或重命名此文件夹,我该怎么办?

    1 回复  |  直到 2 年前
        1
  •  2
  •   CherryDT Ravi Shankar    2 年前

    问题是你通过了 NULL 作为工作目录,因此工作目录将从启动程序继承。如果您从启动程序所在的目录启动启动程序(例如,双击资源管理器中的文件),这意味着您从中启动的进程也将该目录作为工作目录,因此不仅会有一个句柄,而且相对路径也会以该目录为基目录进行解析(在某些情况下,这可能是出乎意料的)。

    解决方案是提取正在启动的程序的路径的目录部分,并将其作为工作目录传递。所以,如果你正在启动,比如说, C:\Windows\System32\notepad.exe ,您需要将其工作目录设置为 C:\Windows\System32 。(如果您从资源管理器启动程序,也会发生这种情况。)

    std::filesystem::path::parent_path 将帮助您完成此任务。