2017-04-17 8 views
0

나는 인터넷에서 많은 것을 검색했지만, 대부분은 reindirect output에 대해 이야기하고 있습니다. 아무도 성공적인 reindirect 입력 예제를 제공하지 않습니다. 아래의 코드의 경우, "ipconfig"또는 "192.168.0.10"명령을 실행했을 때 올바른 결과를 얻었습니다. 이러한 명령을 실행 한 후 하위 프로세스가 끝나기 때문에 입력이 필요하지 않기 때문입니다. 하지만 "ipconfig"명령 대신 "ftp"명령을 실행하면 콘솔 인 자식 프로세스가 다음 입력 명령을 기다리고 있습니다. 그리고 당신이 볼 수있는 것처럼이 경우 콘솔에 11111을 입력으로 쓰려고했습니다. 그러나 콘솔은 입력 명령을받지 못하고 입력 명령을 영원히 기다리지 못했습니다. 나는 성공적으로 응답어떻게 createprocess reindirect input success를 만들 수 있습니까? successally 결과가 다시 나가는 결과를 얻습니다.

#include <windows.h> 
#include <fstream> 
using namespace std; 

int WINAPI WinMain(
        HINSTANCE hInstance, 
        HINSTANCE hPrevInstance, 
        LPSTR lpComLine, 
        int nCmdShow) 
{ 
    SECURITY_ATTRIBUTES secAttr; 
    HANDLE hRead,hWrite; 

char command[256]; 
char testBuf[256] = {0}; 
    strcpy(command, "ipconfig"); 
// strcpy(command, "ping 192.168.0.10")  
// strcpy(command, "ftp"); 

secAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
secAttr.lpSecurityDescriptor = NULL; 
secAttr.bInheritHandle = TRUE; 

HANDLE hTxtFile = CreateFile("tmp.txt", GENERIC_ALL, 0, &secAttr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
if (hTxtFile == INVALID_HANDLE_VALUE) 
{ 
    MessageBox(NULL, "Error createfile", NULL, MB_OK); 
    return 0; 
} 
HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_WRITE, 0, &secAttr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
if (hWriteFile == INVALID_HANDLE_VALUE) 
{ 
    MessageBox(NULL, "Error createWritefile", NULL, MB_OK); 
    return 0; 
} 

STARTUPINFO startupInfo; 
PROCESS_INFORMATION processInfo; 
startupInfo.cb = sizeof(STARTUPINFO); 
GetStartupInfo(&startupInfo); 
startupInfo.hStdError = hTxtFile;  
startupInfo.hStdOutput = hTxtFile; 
startupInfo.hStdInput = hWriteFile; 
startupInfo.wShowWindow = SW_SHOW; 
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; 

char output[10240] = {0}; 
DWORD bytesRead; 

if (!CreateProcess(NULL, command,NULL,NULL,TRUE,NULL,NULL,NULL,&startupInfo,&processInfo)) 
{ 
    MessageBox(NULL, "Error createprocess", NULL, MB_OK); 
    CloseHandle(hWrite); 
    CloseHandle(hRead); 
    return FALSE; 
} 

DWORD processExitCode = 0; 
strcpy(testBuf, "11111\r\n"); 
while (GetExitCodeProcess(processInfo.hProcess, &processExitCode)) 
{ 
    WriteFile(hWriteFile, testBuf, 7, &bytesRead, NULL); 
    if (processExitCode != STILL_ACTIVE) 
    { 
     // MessageBox(NULL, "End process", NULL, MB_OK); 
     break; 
    } 
    Sleep(1000); 
} 

SetFilePointer(hTxtFile, NULL, NULL, FILE_BEGIN); 
ReadFile(hTxtFile, output, 10240, &bytesRead, NULL); 
CloseHandle(hTxtFile); 

MessageBox(NULL, output, NULL, MB_OK); 

return 0; 
} 
+0

1) 때보기 빈 입력 ('NumberOfBytesRead의 == 0 '또는 * ZwReadFile * 반환 *의 STATUS_END_OF_FILE *)은 2)'hStdInput'는'FILE_GENERIC_READ' 액세스 3이 있어야하지 가까운 핸들) 대부분의 프로그램이 필요합니다 간단히 종료하십시오. 따라서 코드가 파일 시스템 파일로 처리되지 않습니다. 또는 프로세스를 만들기 전에'hStdInput' *에 데이터를 써야합니다. – RbMm

+0

4) 일반 메모 - 동기식 공유 파일을 사용할 때 사용하십시오 - 잘못된 파일 공유 * CurrentByteOffset *. * WriteFile *을 호출 할 때 자식 프로세스가 위치를 변경할 수 있기 때문에 생각하는 위치에서 작성할 수 없습니다 (* OVERLAPPED *에서 직접 오프셋을 사용하여 피할 수 있음). 또한 당신의 write change * CurrentByteOffset * 공유 파일 객체에 영향을 미치고 자식 프로세스에 영향을 준다. 5)'processExitCode! = STILL_ACTIVE'를 100 % 신뢰할 수있는 방법으로 사용하지 마라. 자식 프로세스가'ExitProcess (STILL_ACTIVE)'를 호출하면 어떻게 될까? – RbMm

+0

내 프로젝트에서 이미 문제를 발견 했으므로 기본적으로 STARTF_USESTDHANDLES 속성을 사용할 때 문제가 발생합니다. create process는 비 대화식 콘솔을 생성합니다. 즉, create process 호출에서 하나의 명령 행만 실행할 수 있습니다. 내가 마지막 콘솔 출력에 따라 사용자 입력을받는 대화식 리디렉션 콘솔을 만들기 위해 createprocess를 사용할 수있는 아이디어는 없습니까?고마워요. –

답변

2

재 지정을 실행하는 콘솔을 계속이 프로그램에서 "FTP"명령하고 어떻게 (안 "reindirecting") 입력 출력을 리디렉션처럼 동일하게 작동합니다. 물론 데이터 흐름은 반대 방향입니다. 즉, 프로세스는 파일에서을 읽습니다.

HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_WRITE, ...); 

프로세스가 할 수 없습니다 그것에서 읽기 : 당신이 예제 코드에서하는대로 쓰기 위해 핸들을 열 때 차례로 이것은 의미한다. 당신은 읽기 위해 파일을 열어야합니다 :

HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_READ, ...); 

하지만, 이것은 또한 당신이 미리의 과정 로 내려 보낼 입력을 준비해야한다는 것을 의미합니다. 이 과정을 작성한 후 파일 에 쓰는 것은 도움이되지 않습니다.

미리 프로세스에 전송해야하는 데이터를 모르는 경우 표준 입력에 파일을 사용할 수 없지만 (이름이 있거나 익명 인) 파이프와 같은 다른 것을 사용해야합니다.

0

당신은 콘솔 출력을 리디렉션 다음 파일

1)

/* Create a pipe for the child process's STDOUT */ 
    if(!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) 
     BAIL_OUT(-1); 

2)

/* Duplicate the pipe HANDLE */ 
    if (!DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) 
     BAIL_OUT(-1); 

3)

CHAR chBuf[BUFSIZE]; 
    DWORD dwRead; 
    DWORD dwAvail = 0; 
    if (!PeekNamedPipe(hChildStdoutRdDup, NULL, 0, NULL, &dwAvail, NULL) || !dwAvail) 
     return; 
    if (!ReadFile(hChildStdoutRdDup, chBuf, min(BUFSIZE - 1, dwAvail), &dwRead, NULL) || !dwRead) 
     return; 
    chBuf[dwRead] = 0; 

것은 찾아주세요에 버퍼를 작성해야합니다 자세한 내용은 여기 : https://www.codeproject.com/Articles/5531/Redirecting-an-arbitrary-Console-s-Input-Output

+0

http://stackoverflow.com/questions/26398214/redirect-ftp -pipe-in-c 여기서 코드를 변경했는데 완벽하게 작동하지만이 OP와 동일한 문제가 발생합니다. 실제 콘솔에 "ftp"또는 "wmic"를 입력하면 "ftp>"를 수신하고 "123"과 같은 잘못된 명령을 입력하면 "잘못된 명령"이 수신됩니다. 그러나 부모 프로세스와 자식 콘솔 프로세스 간의이 대화 형 작업은 내 코드 또는 인터넷에서 찾은 모든 리디렉션 프로그램에서 발생하지 않습니다. 나는이 데모를 다운로드했고, 그것을 실행할 때도 똑같은 문제가있다. –