Repository: FlaxEngine/FlaxEngine
File: Source/Engine/Platform/Windows/WindowsPlatform.cpp (C++)

Code before:
            return 1;
        }

        SIZE_T bufferSize = 0;
        if (!InitializeProcThreadAttributeList(nullptr, 1, 0, &bufferSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
            attributeList.Resize((int32)bufferSize);
            startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)attributeList.Get();
            if (!InitializeProcThreadAttributeList(startupInfoEx.lpAttributeList, 1, 0, &bufferSize))
            {
                LOG(Warning, "InitializeProcThreadAttributeList failed");
                goto ERROR_EXIT;
            }
        }

        HANDLE inheritHandles[2] = { startupInfoEx.StartupInfo.hStdOutput, startupInfoEx.StartupInfo.hStdError };
        if (!UpdateProcThreadAttribute(startupInfoEx.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inheritHandles, sizeof(inheritHandles), nullptr, nullptr))
        {
            LOG(Warning, "UpdateProcThreadAttribute failed");
            goto ERROR_EXIT;
        }
    }

    // Create the process
    PROCESS_INFORMATION procInfo;
    if (!CreateProcessW(nullptr, const_cast<LPWSTR>(String(cmdLine).GetText()), nullptr, nullptr, TRUE, dwCreationFlags, (LPVOID)environmentStr, String(workingDir).GetText(), &startupInfoEx.StartupInfo, &procInfo))
    {
        LOG(Warning, "Cannot start process '{0}'. Error code: 0x{1:x}", cmdLine, static_cast<int64>(GetLastError()));
        goto ERROR_EXIT;
    }

    if (environmentStr)
        Allocator::Free(environmentStr);

    if (stdOutRead != nullptr)
    {
        // Keep reading std output and std error streams until process is running
        Array<char> rawData;
        Array<Char> logData;
        do
        {
            ReadPipe(stdOutRead, rawData, logData, LogType::Info);
            ReadPipe(stdErrRead, rawData, logData, LogType::Error);
            Sleep(1);
        } while (IsProcRunning(procInfo.hProcess));
        ReadPipe(stdOutRead, rawData, logData, LogType::Info);
        ReadPipe(stdErrRead, rawData, logData, LogType::Error);
    }
    else
    {
        WaitForSingleObject(procInfo.hProcess, INFINITE);

Review comment (bug):
For `workingDir` we should pass `nullptr` if it's empty so it picks the current process workspace.

Code after:
            return 1;
        }

        SIZE_T bufferSize = 0;
        if (!InitializeProcThreadAttributeList(nullptr, 1, 0, &bufferSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
            attributeList.Resize((int32)bufferSize);
            startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)attributeList.Get();
            if (!InitializeProcThreadAttributeList(startupInfoEx.lpAttributeList, 1, 0, &bufferSize))
            {
                LOG(Warning, "InitializeProcThreadAttributeList failed");
                goto ERROR_EXIT;
            }
        }

        HANDLE inheritHandles[2] = { startupInfoEx.StartupInfo.hStdOutput, startupInfoEx.StartupInfo.hStdError };
        if (!UpdateProcThreadAttribute(startupInfoEx.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inheritHandles, sizeof(inheritHandles), nullptr, nullptr))
        {
            LOG(Warning, "UpdateProcThreadAttribute failed");
            goto ERROR_EXIT;
        }
    }

    // Create the process
    PROCESS_INFORMATION procInfo;
    if (!CreateProcessW(nullptr, const_cast<LPWSTR>(String(cmdLine).GetText()), nullptr, nullptr, TRUE, dwCreationFlags, (LPVOID)environmentStr, workingDir.HasChars() ? workingDir.Get() : nullptr, &startupInfoEx.StartupInfo, &procInfo))
    {
        LOG(Warning, "Cannot start process '{0}'. Error code: 0x{1:x}", cmdLine, static_cast<int64>(GetLastError()));
        goto ERROR_EXIT;
    }

    if (environmentStr)
        Allocator::Free(environmentStr);

    if (stdOutRead != nullptr)
    {
        // Keep reading std output and std error streams until process is running
        Array<char> rawData;
        Array<Char> logData;
        do
        {
            ReadPipe(stdOutRead, rawData, logData, LogType::Info);
            ReadPipe(stdErrRead, rawData, logData, LogType::Error);
            Sleep(1);
        } while (IsProcRunning(procInfo.hProcess));
        ReadPipe(stdOutRead, rawData, logData, LogType::Info);
        ReadPipe(stdErrRead, rawData, logData, LogType::Error);
    }
    else
    {
        WaitForSingleObject(procInfo.hProcess, INFINITE);