Search code examples
c++batch-filecmdcreateprocess

cmd.exe immediately closes after calling with CreateProcess


I am trying to execute a batch file using CreateProcess function, but the cmd.exe immediately closes without opening the executing the batch file.

An argument (path of a directory) is also passed.

The c++ code is :

int main()
{
    std::wstring cmdPath;
    std::wstring batchFile;
    batchFile = L"\"B:\\code\\Batch\\all_files.bat\"";
    std::wstring args = L"\"B:\\code\\Batch\"";

    {
        wchar_t cmdP[500] = L"  ";
        GetEnvironmentVariable(L"COMSPEC", cmdP, 500);
        cmdPath = cmdP;
    }

    std::wstring CmdLine = L"/c " + batchFile + L" " + args;

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    if (!
        CreateProcess
        (
            cmdPath.c_str(),
            const_cast<LPWSTR>(CmdLine.c_str()),
            NULL, NULL, FALSE,
            CREATE_NEW_CONSOLE,
            NULL, NULL,
            &si,
            &pi
        )
        )
    {
        std::cout << "bad";
        std::cin.get();
        return 1;
    }
    std::cout << "yay......\n";
    std::cin.get();
    return 0;
}

And the Batch file is

echo hello.

set directory=%~1

cd %directory%

dir > files.txt

pause

exit 0

The Output

yay......

is got but the file files.txt nor the output of echo hello. is got.


Solution

  • The answer it seemed was the need to enclose the whole command line (except \c) with quotes.

    hence the program becomes :

    int main()
    {
        std::wstring cmdPath;
        std::wstring batchFile;
        batchFile = L"\"B:\\Source code\\Batch\\all_files.bat\"";
        std::wstring args = L"\"B:\\Source code\\Batch\"";
    
        {
            wchar_t cmdP[500] = L"  ";
            GetEnvironmentVariable(L"COMSPEC", cmdP, 500);
            cmdPath = cmdP;
        }
    
        std::wstring CmdLine = L"/c " + std::wstring(L"\"") + batchFile + L" " + args + L"\"";
    
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));
        if (!
            CreateProcess
            (
                cmdPath.c_str(),
                const_cast<LPWSTR>(CmdLine.c_str()),
                NULL, NULL, FALSE,
                CREATE_NEW_CONSOLE,
                NULL, NULL,
                &si,
                &pi
            )
            )
        {
            std::cout << "bad";
            std::cin.get();
            return 1;
        }
        std::cout << "yay......\n";
        std::cin.get();
        return 0;
    }
    

    EDIT: for the final code I changed /k back to /c