2017-04-17 29 views
0

我在互联网上搜索了很多,但他们大多数都在谈论reindirect输出。没有人给出任何成功的reindirect输入示例。对于我下面的代码,当我运行命令“ipconfig”或“192.168.0.10”时,它会给出正确的输出,因为在运行这些命令后子进程结束,不需要输入。但是当我运行命令“ftp”而不是“ipconfig”时,控制台的子进程正在等待下一个输入命令。正如你所看到的,我试图在这种情况下将11111作为输入写入控制台。然而,控制台没有收到我的输入命令并永远等待输入命令。我怎样才能成功地应对这个计划“ftp”的命令,并保持控制台运行我怎样才能让createprocess reindirect输入成功,我已经成功地获得reindirect输出结果

#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)需要关闭句柄,你不做2)'hStdInput'必须有'FILE_GENERIC_READ'访问3)大多数程序时查看空输入('NumberOfBytesRead == 0'或* ZwReadFile *回报* STATUS_END_OF_FILE *)只需退出 - 所以你的代码将不会与文件系统文件一起工作。或者在创建进程之前需要将数据写入'hStdInput' *。 – RbMm

+0

4)一般说明 - 在使用同步共享文件时使用它 - 不正确 - 文件共享* CurrentByteOffset *。当你调用* WriteFile *时,你可以不从你认为的位置写入,因为子进程可以改变位置(这可以避免在* OVERLAPPED *中使用直接偏移)。你的写改变* CurrentByteOffset *在共享文件对象,并影响子进程5)使用'processExitCode!= STILL_ACTIVE'不是100%可靠的方式 - 如果子调用ExitProcess(STILL_ACTIVE)'? – RbMm

+0

我已经在我的项目中找到了问题,所以基本上在我们使用STARTF_USESTDHANDLES属性时。 createprocess将创建非交互式控制台,这意味着它只能在createprocess调用中运行一个命令行。任何想法我可以使用createprocess创建一个交互式重定向控制台,它根据最后的控制台输出接受用户输入?非常感谢 –

回答

2

重定向(不是“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”时,我们会收到“无效命令”。但是,父进程和子控制台进程之间的这种交互操作不会发生在我的代码或我在互联网上找到的所有重定向程序中。我已经下载了这个演示,并且在运行它时也遇到了同样的问题 –

相关问题