Search code examples
c++windowscommand-prompt

Launch command line window in hidden mode from a C++ code and read output log file


On windows machine, My code runs ShellExecute to launch abc.exe with SW_HIDE as the last argument to hide the launched command line window. This runs fine as desired.

std::string torun = "/c abc.exe >abc.log";
HINSTANCE retVal = ShellExecute(NULL, _T("open"), _T("cmd"), std::wstring(torun.begin(), torun.end()).c_str(), NULL, SW_HIDE);

My issue is that abc.log which captures the output of abc.exe is not accessible even though it is written successfully. Code below returns "file does not exist".

std::string filename = "abc.log";
if (_access(filename.c_str(), 0) == -1)
    std::cout<<"file does not exist";
else
    std::cout<<"file exists";

I need to read the content of this log file after checking that it exists. Code below also returns "file does not exist".

ifstream fin;
fin.open("abc.log");
if(fin)
    std::cout<<"file exists";
else
    std::cout<<"file does not exist";

Is there some permission issue? I have two needs - launch abc.exe on a command line window which is hidden or runs behind all open windows and also be able to read the abc.log. Appreciate the help.


Solution

  • You need to wait for the child process to finish:

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    #include <tchar.h>   
    #include <shellapi.h>
    ...
    
    SHELLEXECUTEINFO sei = { sizeof(sei), SEE_MASK_NOCLOSEPROCESS|SEE_MASK_FLAG_NO_UI };
    sei.lpFile = TEXT("cmd.exe");
    sei.lpParameters = TEXT("/C ping localhost > abc.log"); // Command that takes a while to complete
    sei.nShow = SW_HIDE;
    if (ShellExecuteEx(&sei))
    {
        if (sei.hProcess)
        {
            WaitForSingleObject(sei.hProcess, INFINITE);
            CloseHandle(sei.hProcess);
            FILE*file = fopen("abc.log", "r");
            if (file)
            {
                char buf[1337];
                size_t cb = fread(buf, 1, sizeof(buf), file);
                if (cb)
                {
                    buf[min(cb, sizeof(buf)-1)] = '\0';
                    MessageBoxA(NULL, buf, "stdout started with", 0);
                }
                fclose(file);
            }
        }
    }
    

    This is still a bit lazy, the optimal way to read stdout from a child process is to call CreateProcess with pipes.