【发布时间】:2017-04-17 10:11:51
【问题描述】:
我在互联网上搜索了很多,但大多数都在谈论重定向输出。没有人给出任何成功的重定向输入示例。对于下面的代码,当我运行命令“ipconfig”或“192.168.0.10”时它给出了正确的输出,因为子进程在运行这些命令后结束,不需要输入。但是当我运行命令“ftp”而不是“ipconfig”时,控制台的子进程正在等待下一个输入命令。如您所见,在这种情况下,我尝试将 11111 作为控制台的输入。但是控制台没有收到我的输入命令并永远等待输入命令。如何在此程序中成功响应“ftp”命令并保持控制台运行
#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;
}
【问题讨论】:
-
1) 需要关闭句柄,但您不这样做 2)
hStdInput必须有FILE_GENERIC_READ访问权限 3) 大多数程序在查看空输入时(NumberOfBytesRead == 0或 ZwReadFile return STATUS_END_OF_FILE )简单地退出 - 因此您的代码将无法与文件系统文件一起使用。或者您需要在创建进程之前将数据写入hStdInput。 -
4) 一般说明 - 在使用时使用同步共享文件 - 不正确 - 文件共享 CurrentByteOffset。当您调用 WriteFile 时,您不能从您认为的位置写入,因为子进程可以更改位置(这可以通过在 OVERLAPPED 中使用直接偏移来避免)。您在共享文件对象中的写入更改 CurrentByteOffset 并影响子进程 5)使用
processExitCode != STILL_ACTIVE不是 100% 可靠的方式 - 如果子调用ExitProcess(STILL_ACTIVE)怎么办? -
我已经在我的项目中发现了问题,所以基本上当我们使用 STARTF_USESTDHANDLES 属性时。 createprocess 将创建非交互式控制台,这意味着它只能在 createprocess 调用中运行一个命令行。知道我可以使用 createprocess 创建一个交互式重定向控制台,该控制台根据最后一个控制台输出获取用户输入吗?非常感谢
-
没有“非交互式控制台”之类的东西,由于您正在重定向输入,因此无论如何都不涉及控制台。问题是您试图像使用管道一样使用文件,这是行不通的。
-
stackoverflow.com/questions/26398214/redirect-ftp-pipe-in-c 在这里,我更改了我的代码,它现在可以正常工作,但我遇到了与这个 OP 相同的问题。当我们在真实控制台中输入“ftp”或“wmic”时,我们会收到“ftp>”,而当我们输入像“123”这样的无效命令时,我们会收到“无效命令”。但是这种父进程和子控制台进程之间的交互操作并没有发生在我的代码或我在互联网上找到的所有重定向程序中。所以还没有真正看到一个 VC 控制台像真正的 cmd.exe 控制台一样工作
标签: c++ winapi createprocess