none
C언어 CreateProcess()로 만든 cmd의 입력제어 RRS feed

  • 질문

  • CreateProcess 함수를 이용해 cmd창을 열어 "cd .." 명령을 3번 입력하려고 합니다

    STARTINFO 구조체의 hStdInput을 파이프 핸들로 지정해서 입력을 제어하려고 합니다

    1번째 "cd .."명령은 정상적으로 작동이 됩니다만

    2번째는 More? 라는 문자가 나타나고

    3번째부터는 아무런 동작도 하지 않습니다

    cd 명령 뿐만 아니라 다른 명령을 사용해도 마찬가지 입니다

    질문은 아래 3가지입니다

    1. 여러번 명령을 입력해도 정상적으로 작동하게 하려면 어떻게 고쳐야하나요?

    2. 현재 안되는 이유는 뭔가요?

    3. TerminateThread와 TerminateProcess 함수로 CreateProcess함수의 cmd를 종료하려고 하는데 바로 종료가 되지 않습니다

        바로 종료시킬 방법이 있을까요?

    아래는 제가 짠 코드입니다 언어는 C를 사용했습니다

    #include <stdio.h>
    #include <Windows.h>
    #include <tchar.h>

    int main(void)
    {
    SECURITY_ATTRIBUTES se = { 0 };
    se.nLength = sizeof(se);
    se.bInheritHandle = TRUE;
    se.lpSecurityDescriptor = NULL;

    HANDLE hCRead, hCWrite;
    CreatePipe(&hCRead, &hCWrite, &se, 0);

    const TCHAR com[MAX_PATH] = _T("cmd");
    PROCESS_INFORMATION pi = { 0 };
    STARTUPINFO st = { 0 };
    st.cb = sizeof(st);
    st.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    st.hStdError = GetStdHandle(STD_OUTPUT_HANDLE);
    st.hStdInput = hCRead;
    st.dwFlags = STARTF_USESTDHANDLES;
    CreateProcess(NULL, com, NULL, NULL, TRUE, 0, NULL, NULL, &st, &pi);
    CloseHandle(hCRead);

    char buff[MAX_PATH] = { 0 };
    DWORD written;
    char com2[30] = "cd ..";

            for(int i = 0; i < 3; i++)
    {
    WriteFile(hCWrite, com2, sizeof(com2), &written, NULL);
    }

    CloseHandle(hCWrite);
    TerminateThread(pi.hThread, 0);
    TerminateProcess(pi.hProcess, 0);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);

    getchar();
    }


    • 편집됨 VItsel 2019년 7월 27일 토요일 오후 2:03
    2019년 7월 27일 토요일 오후 1:57

모든 응답

  • 안녕하세요
    포럼을 이용해 주셔서 감사합니다.

    >>여러번 명령을 입력해도 정상적으로 작동하게 하려면 어떻게 고쳐야하나요? 현재 안되는 이유는 뭔가요?

    printf() 와 fprintf()와 같은 C 런타임 함수를 사용하는 자식 프로세스는 리디렉션 될 때 제대로 작동하지 않을 수 있습니다. C 런타임 함수는 별도의 IO 버퍼를 유지합니다. 리디렉션될 겨우, 매번 IO 호출 후에 이러한 버퍼가 즉시로 플러시되지 않을 수 있습니다.
    결과적으로 printf() 호출의 리디렉션 파이프 출력 또는 getch() 호출부터의 입력이 즉시 플러시되지 않으며, 경우에 따라 지연 혹은 무한 지연이 발생합니다. 자식 프로세스가 C 런타임 IO 함수를 호출 할 때마다 IO 버퍼를 플러시하는 경우 이 문제를 방지 할 수 있습니다. 자식 프로세스 만이 자신의 C 런타임 IO 버퍼를 플러시 할 수 있습니다. 프로세스는 fflush() 함수를 호출하여 C 런타임 IO 버퍼를 플러시 할 수 있습니다.

    해당 링크를 참조하시기 바랍니다: https://support.microsoft.com/en-sg/help/190351/how-to-spawn-console-processes-with-redirected-standard-handles

    아래 부분을:

    char com2[30] = "cd ..";

            for(int i = 0; i < 3; i++)
    {
    WriteFile(hCWrite, com2, sizeof(com2), &written, NULL);
    }


    아래 코드로 대채하시기 바랍니다:

    CHAR cmd2[] = "cd..\n";
                                    "cd..\n"
                                    "cd..\n";

                                    WriteFile(hCWrite, cmd2, sizeof(cmd2), &dwWritten, NULL);


    >> TerminateThread와 TerminateProcess 함수로 CreateProcess함수의 cmd를 종료하려고 하는데 바로 종료가 되지 않습니다. 바로 종료시킬 방법이 있을까요?

    해당 함수는 프로세스 내의 모든 스레드의 실행을 중지하고 모든 보류중인(pending) I/O의 취소를 요청합니다. 종료 된 프로세스는 보류중인 모든 I/O가 완료되거나 취소 될 때까지 exit 할 수 없습니다. 
    프로세스가 종료되면 프로세스에 대한 오픈 핸들이 있는 모든 프로세스가 해당 핸들을 릴리스 할 때까지 해당 커널 객체가 삭제되지 않습니다.
    TerminateProcess는 비동기식(asynchronous)입니다. 그래서 종료를 시작하고 즉시 리턴합니다. 프로세스가 종료되었는지 확인하려면 프로세스의 핸들과 함께 WaitForSingleObject 함수를 호출할수 있습니다. 프로세스는 자체가 종료되는 것을 막을 수는 없습니다.

    TerminateThread 와 TerminateProcess 함수는 기본적으로 안전한 호출 방법이 없으므로 절대로 호출해서는 안됩니다. 해당 링크를 참조하시기 바랍니다:
    https://devblogs.microsoft.com/oldnewthing/20180831-00/?p=99625

    MSDN Community Support Ricky

    다른 커뮤니티 멤버에게 도움이 될 수 있게 문제를 해결 한 답변을 '답변으로 표시'를 클릭하시고 그렇지 않은 경우 '답변으로 표시 취소'를 클릭하시기 바랍니다. MSDN 서포트에 대한 의견이나 불만이 있을 경우 MSDNFSF@microsoft.com 으로 연락하시기 바랍니다.

     
    2019년 7월 29일 월요일 오전 8:56
    중재자