-1

I can't seem to get this working and I have tried and tried. At the momenet it just prints out this...

#include <stdio.h>
#include <string.h>
#include <windows.h>

#define BUFSIZE 2048

HANDLE stdout_write, stdout_read;

void create_pipe(void)
{
    SECURITY_ATTRIBUTES attr;
    attr.nLength = sizeof(SECURITY_ATTRIBUTES);
    attr.bInheritHandle = TRUE;
    attr.lpSecurityDescriptor = NULL;

    if (!CreatePipe(&stdout_read, &stdout_write, &attr, 0)) {
        printf("CreatePipe() failed\n");
    } else {
        printf("CreatePipe() success\n");
    }

    if (!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0)) {
        printf("SetHandleInformation() failed\n");
    } else {
        printf("SetHandleInformation() success\n");
    }
}


void read_pipe_output(void)
{
    char buf[BUFSIZE] = {0};
    DWORD dwRead = 0;
    BOOL bsuccess = 0;

    for (;;) {
        bsuccess = ReadFile(stdout_read, buf, BUFSIZE, &dwRead, NULL);
        if( ! bsuccess || dwRead == 0 ) break;
    }

    printf("buf: %s\n", &buf[0]);
}


int main(int argc, char *argv[])
{
    char *fuck = "C:\\Windows\\System32\\cmd.exe";
    char *cmd = "C:\\Windows\\System32\\cmd.exe /c dir";

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    memset(&si, 0x0, sizeof(si));
    memset(&pi, 0x0, sizeof(pi));

    si.cb = sizeof(STARTUPINFO);
    si.wShowWindow = FALSE;
    si.hStdOutput = stdout_write;
    si.hStdError = stdout_write;
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

    create_pipe();

    if (!CreateProcessA(fuck, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
       printf("error\n");
    } else {
        CloseHandle(stdout_write);
    }

    read_pipe_output();
  



    CloseHandle(stdout_read);
    printf("completed\n");
    
    return 0;
}

I want to print the output of "ls" which works fine but I want to use a pipe so I can do some stuff with the output data.

Any help appreciated!

M.M
  • 138,810
  • 21
  • 208
  • 365
n c
  • 45
  • 1
  • 7
  • What is `ls` on windows? – nevilad Mar 21 '21 at 16:50
  • lol i see what you mean. But i have tested it without the PIPEs and it printed the contents of the directory out? I will try it with "dir" then lol. EDIT: I tried with "dir" and still the same... its not a problem with using "ls". – n c Mar 21 '21 at 16:54
  • `stdout_write` is not initialized when is written to `si.hStdOutput` and `si.hStdError`. – nevilad Mar 21 '21 at 17:20
  • When you use `STARTF_USESTDHANDLES` you should initialize also `hStdInput` member. To print a character you should use `%c`, not `%s`: `printf("buf: %c\n", buf[0]);`. You call `CreateProcess` with `bInheritHandles` set to FALSE, it should be set to TRUE when you want to use `STARTF_USESTDHANDLES`. – nevilad Mar 21 '21 at 17:33
  • @nevilad i use attr.bInheritHandle = TRUE; not FALSE? – n c Mar 21 '21 at 18:03
  • @nevilad i updated the code but still not working. Yea the printf was an error i meant to use &buf[0] to use %s for the string. I have also moved STARTF_USESTDHANDLES etc to the bottom. Still not working though. – n c Mar 21 '21 at 18:13
  • Does this answer your question? [How to read output from cmd.exe using CreateProcess() and CreatePipe()](https://stackoverflow.com/questions/35969730/how-to-read-output-from-cmd-exe-using-createprocess-and-createpipe) – nevilad Mar 21 '21 at 19:28
  • @nevilad Sorry but it doesnt, I have tried some of the examples it they do not work... i get many errors. This should be such a simple thing! It is so annoying. Windows is annoying. I could have easily one this in linux. :/ – n c Mar 21 '21 at 20:43
  • Rolled back the last edit -- this site uses a Q/A format, the question goes in the question box and the answer in the answer box – M.M Mar 22 '21 at 03:43

1 Answers1

1

Read the question as it has been edited to include my answer. I will include the code here also.

#include <stdio.h>
#include <string.h>
#include <windows.h>

#define BUFSIZE 2048

HANDLE stdout_write, stdout_read;

void create_pipe(void)
{
    SECURITY_ATTRIBUTES attr;
    attr.nLength = sizeof(SECURITY_ATTRIBUTES);
    attr.bInheritHandle = TRUE;
    attr.lpSecurityDescriptor = NULL;

    if (!CreatePipe(&stdout_read, &stdout_write, &attr, 0)) {
        printf("CreatePipe() failed\n");
    } else {
        printf("CreatePipe() success\n");
    }

    if (!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0)) {
        printf("SetHandleInformation() failed\n");
    } else {
        printf("SetHandleInformation() success\n");
    }
}


void read_pipe_output(void)
{
    char buf[BUFSIZE];
    DWORD dwRead = 0;
    BOOL bsuccess = 0;

    memset(&buf, 0x0, sizeof(buf));

    for (;;) {
        bsuccess = ReadFile(stdout_read, buf, BUFSIZE, &dwRead, NULL);
        if( ! bsuccess || dwRead == 0 ) break;
    }

    printf("buf: %s\n", &buf[0]);
}


int main(int argc, char *argv[])
{
    char *cmd = "ls";

    create_pipe();

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    memset(&si, 0x0, sizeof(si));
    memset(&pi, 0x0, sizeof(pi));

    si.cb = sizeof(STARTUPINFO);
    si.wShowWindow = FALSE;
    si.hStdOutput = stdout_write;
    si.hStdError = stdout_write;
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

    if (!CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
       printf("error\n");
    } else {
        printf("CreateProcess() success\n");
        CloseHandle(stdout_write);
    }

    
    WaitForSingleObject( pi.hProcess, INFINITE );

    read_pipe_output();

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    CloseHandle(stdout_read);
    printf("completed\n");
    
    return 0;
}
n c
  • 45
  • 1
  • 7
  • 1
    It would improve the answer to also explain or point out what was wrong with the original code – M.M Mar 22 '21 at 03:45
  • Yes, there are many questions. You didnt make `stdout_read` inheritable, you didnt initialize `hStdInput` member of `STARTUPINFO` but able to read child process output from `stdout_read`. How the child knows it should write to `stdout_read`? Another question is how you were able to run `ls` and `dir` with `CreateProcess`. This link (https://stackoverflow.com/questions/46079225/creating-dir-command-using-createprocess-function-failed-with-error-code-2) states that at least `dir` should be run using `cmd /c dir`. – nevilad Mar 22 '21 at 19:37
  • @nevilad https://stackoverflow.com/a/54139913/9633400 (last answer in the link you provided answers the question as to ls and dir... I did think that may have been the case lol.) At least i know now to just use cmd /c command but yea that is how it was working. – n c Jun 13 '21 at 21:11
  • The code in the answer is wrong - it uses `char *cmd = "ls";`, the original code of the question is the same, but the last edited version of the question is right, it uses `char *cmd = "C:\\Windows\\System32\\cmd.exe /c dir";`. Correct the answer. – nevilad Jun 14 '21 at 10:51