Search code examples
c++winapipipecreateprocessfar

How to execute commands in FarManager running in Windows console


I have a client server application. Using the CreateProcess() function, a new process is created on the server, which is actually like a remote console. The client sends a command, it is executed in the server console and returns the result back to the server. To communicate with the console, I use WriteFile() and ReadFile(). This part works great.

But I also need to be able to run FarManager in the server console and manage it.

I am able to run FarManager on the server using an environment variable, or by directly specifying it when creating a process. But after running the program, I can't issue any commands (for example, pressing the down arrow). It looks like the current implementation of pipes is not suitable for this task.

Can anyone suggest what might be useful for this?

CreateProcess function:
I am not attaching all the related structures, because the problem does not seem to be in the process itself

TCHAR szCmdline[] = TEXT("C:\\Windows\\System32\\cmd.exe");
TCHAR prog[] = TEXT("D:\\Program Files\\Far Manager x86\\Far.exe");

// Create the child process. 
bSuccess = CreateProcess(
    prog,           // far
    szCmdline,      // command line 
    NULL,           // process security attributes 
    NULL,           // primary thread security attributes 
    TRUE,           // handles are inherited
    CREATE_NEW_CONSOLE,   // creation flags
    NULL,           // use parent's environment 
    NULL,           // use parent's current directory 
    &si,            // STARTUPINFO pointer 
    &pi);           // receives PROCESS_INFORMATION 

WriteToPipe function:

bool WriteToPipe(char* com)
{
    OVERLAPPED osWrite = { 0 };
    DWORD dwWritten;
    DWORD dwRes;
    BOOL fRes;

    // Create this write operation's OVERLAPPED structure's hEvent.
    osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osWrite.hEvent == NULL) {
        // error creating overlapped event handle
        throw std::exception("Error creating overlapped event");
    }

    // Issue write.
    if (!WriteFile(console_stdIn_wr, com, strlen(com), &dwWritten, &osWrite)) {
        if (GetLastError() != ERROR_IO_PENDING) {
            // WriteFile failed, but isn't delayed. Report error and abort.
            std::cout << " WriteFile failed, but isn't delayed" << std::endl;
            fRes = FALSE;
        }
        else {
            // Write is pending.
            dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
            switch (dwRes)
            {
                // OVERLAPPED structure's event has been signaled. 
            case WAIT_OBJECT_0:
                if (!GetOverlappedResult(console_stdIn_wr, &osWrite, &dwWritten, FALSE))
                    fRes = FALSE;
                else
                    // Write operation completed successfully.
                    fRes = TRUE;
                break;
            default:
                // An error has occurred in WaitForSingleObject.
                // This usually indicates a problem with the
                // OVERLAPPED structure's event handle.
                fRes = FALSE;
                break;
            }
        }
    }
    else {
        // WriteFile completed immediately.
        fRes = TRUE;
    }


    CloseHandle(osWrite.hEvent);
    return fRes;
}

I don't understand how I can issue commands to the open FarManager? Which function is worth looking at, and is the current implementation of pipes suitable for this?


Solution

  • I am attaching my solution based on the advice of @YurkoFlisk. Maybe it can be useful for someone

    //Execute command in FarManager
    //nVirtKey - code of virtual key to run in far
    void RunFar(int nVirtKey){
        std::cout << "Key code "<< nVirtKey << std::endl;
    
        //Create structure with buttons and their state
        INPUT inputs[2] = {};
        ZeroMemory(inputs, sizeof(inputs));
    
        //Set key, that must be "pressed"
        inputs[0].type = INPUT_KEYBOARD;
        inputs[0].ki.wVk = nVirtKey;
    
        //Set state of key
        inputs[1].type = INPUT_KEYBOARD;
        inputs[1].ki.wVk = nVirtKey;
        inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
    
        //Set position of window with FarManger to the foreground (by the handle of window)
        SetForegroundWindow(hwnd);
    
        //Send key structure to window
        UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));           
    }