问题描述
我试图像正常的cmd.exe一样打印接收到stdout的cmd命令的输出和输入.我可以使用功能_popen
,但是当我启动像Python或Powershell这样的程序时,它不起作用. 所以我需要子进程的输出,并且能够将命令发送到子进程.
Im trying to print the output and input of cmd commands recieved to stdout just like a normal cmd.exe would do.I could use the function _popen
but when i start a program like Python or Powershell whith it, it doesnt work. So i Need the Output of the child process and be able to send commands to the child process.
有一个类似的问题此处
所以我从此链接看起来像这样:
So i modified the code from this link to look like this:
void WriteToPipe(char* command){
DWORD dwRead, dwWritten;
BOOL bSuccess = FALSE;
bSuccess = WriteFile(g_hChildStd_IN_Wr, command, strlen(command), &dwWritten, NULL);
// Close the pipe handle so the child process stops reading.
if (!CloseHandle(g_hChildStd_IN_Wr))
ErrorExit(TEXT("StdInWr CloseHandle"));
}
void ReadFromPipe(void){
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
BOOL bSuccess = FALSE;
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
bSuccess = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL);
//bSuccess = PeekNamedPipe(g_hChildStd_OUT_Rd, NULL, BUFSIZE, &dwRead, &dwTotalAvailBytes, &dwBytesLeft);
}
主循环如下:
CreateChildProcess("C:\\Python27\\python.exe");
char input_buffer[100] = { 0 };
while (1){
fgets(input_buffer, 99, stdin);
WriteToPipe(input_buffer);
ReadFromPipe();
}
其他所有(来自代码)保持不变.
everything else (from the code) stayed the same.
现在我的问题是,我想在同一进程中输入多个命令,但是WriteToPipe中有一个CloseHandle功能,在关闭句柄之后,我无法输入更多命令.
Now my Problem is, i want to enter multiple commands to the same process, but there is a CloseHandle fucntion in WriteToPipe, after the handle is closed i cant enter more commands.
如何获取有效的HANDLE以便向进程写入多个命令?
推荐答案
将ReadFromPipe()放在单独的线程中;我的代码在这里是垃圾,但它是有效的代码,仅用于测试目的.
put ReadFromPipe() in a separate Thread;my code here is a garbage but it is working code, it is for test purpose only.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFSIZE 4096
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
HANDLE g_hInputFile = NULL;
int CreateChildProcess(TCHAR *szCmdline);
void PrintError(char *text,int err);
int InitPipes();
int WriteToPipe(char* command){
DWORD dwRead, dwWritten;
BOOL bSuccess = FALSE;
SetLastError(0);
WriteFile(g_hChildStd_IN_Wr, command, strlen(command), &dwWritten, NULL);
bSuccess=GetLastError();
PrintError("WriteToPipe",bSuccess);
return (bSuccess==0)||(bSuccess==ERROR_IO_PENDING);
}
int ReadFromPipe(void){
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
BOOL bSuccess = FALSE;
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetLastError(0);
while(
ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL)
&&
WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL)
);
bSuccess=GetLastError();
PrintError("ReadFromPipe",bSuccess);
return (bSuccess==0)||(bSuccess==ERROR_IO_PENDING);
}
HANDLE hThread;
int __stdcall ThreadProc(int arg){
while(ReadFromPipe())
;
return 0;
}
int main(){
char input_buffer[100] = { 0 };
if(!InitPipes()){
printf("Failed to CreatePipes\n");
return -1;
}
if(!CreateChildProcess("cmd.exe")){
printf("Failed to create child process\n");
return -2;
}
hThread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
while (1){
fgets(input_buffer, 99, stdin);
if(!WriteToPipe(input_buffer)) break;
}
printf("Program terminated\n");
return 0;
}
int CreateChildProcess(TCHAR *szCmdline){
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bSuccess = FALSE;
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
// Set up members of the STARTUPINFO structure.
// This structure specifies the STDIN and STDOUT handles for redirection.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
bSuccess = CreateProcess(NULL,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
// If an error occurs, exit the application.
if ( bSuccess ){
// Close handles to the child process and its primary thread.
// Some applications might keep these handles to monitor the status
// of the child process, for example.
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
}
return bSuccess;
}
int InitPipes(){
SECURITY_ATTRIBUTES saAttr;
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
return 0;
if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
return 0;
if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
return 0;
if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
return 0;
return 1;
}
void PrintError(char *text,int err){
DWORD retSize;
LPTSTR pTemp=NULL;
if(!err) return;
retSize=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
err,
LANG_NEUTRAL,
(LPTSTR)&pTemp,
0,
NULL );
if(pTemp) printf("%s: %s\n",text,pTemp);
LocalFree((HLOCAL)pTemp);
return ;
}
这篇关于通过管道重定向CMD.exe在c中的输出和输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!