读书人

怎么在一个程序中调用另一个命令行程序

发布时间: 2012-01-16 23:36:51 作者: rapoo

如何在一个程序中调用另一个命令行程序,并重定向输入的问题。分太多,解决立即结贴
现有一个命令行程序contest.exe,它读取标准输入,并将结果写入到一个文件中。
现在要实现在一个界面程序(wintest.exe)中调用contest.exe,并向它的标准输入发一些数据。
我根据MSDN文档,利用CreatePipe和CreateProcess来实现,但是结果老是不对,contest.exe没有接收到数据,非常郁闷。
请各位看看代码,帮忙改正!

下面是contest.exe的源代码,不能修改:
#include "stdafx.h "
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
char *command = NULL;
command=argv[1];

if( !strcmp( command, "stdin " ))
{
FILE *input,*output;
input=stdin;
if (input != NULL)
{
output=fopen(argv[2], "wb ");

char buf[1024];
int readRet=0;
while (!feof(input))
{
readRet = fread(buf, sizeof(char), 1024, input);
buf[readRet]= '\0 ';
fwrite(buf,sizeof(char),readRet,output);
printf( "%s ",buf);
}
fflush(output);
}
}

return 0;
}

以上代码编辑后,我在命令行下运行它,命令格式为:contest.exe std result.txt,可以得到正确结果:

下面是我写的另外一个程序中调用contest.exe的代码:
int ret;
SECURITY_ATTRIBUTES sa1,sa2;
sa1.nLength = sizeof(SECURITY_ATTRIBUTES);
sa1.lpSecurityDescriptor = NULL;
sa1.bInheritHandle = TRUE;
sa2.nLength = sizeof(SECURITY_ATTRIBUTES);
sa2.lpSecurityDescriptor = NULL;
sa2.bInheritHandle = TRUE;

HANDLE hReadPipe2,hWritePipe2,hReadPipe1,hWritePipe1;

CreatePipe( &hReadPipe1, &hWritePipe1, &sa1, 0 );
CreatePipe( &hReadPipe2, &hWritePipe2, &sa2, 0 );

STARTUPINFO si;
::ZeroMemory(&si,sizeof(si));
si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.hStdInput=hReadPipe2;
si.hStdOutput=si.hStdError=hWritePipe1;
si.cb=sizeof(si);
PROCESS_INFORMATION processInfo;
char cmdLine[] = "contest.exe stdin result.txt ";
ZeroMemory( &processInfo , sizeof(PROCESS_INFORMATION) );
ret=CreateProcess(NULL, cmdLine, NULL,NULL,1,0,NULL,NULL,&si,&processInfo);
if( !ret ) return;


char buff[]= "this is a test string. ";
DWORD bytesRead=1024;

ret = WriteFile( hWritePipe2, buff, bytesRead, &bytesRead, 0 );
if( !ret ) return;
CloseHandle( hWritePipe2 );

Sleep(1000);
TerminateProcess( processInfo.hProcess, 0 );
CloseHandle( hReadPipe1 );
CloseHandle( hReadPipe2 );
CloseHandle( hWritePipe1 );




[解决办法]
参考
http://community.csdn.net/Expert/topic/5225/5225434.xml?temp=.570904
[解决办法]
CreateProcess跟操作系统有点关系的,你是2000系统还是xp?
[解决办法]
// 只做了STDIN的重定向, STDOUT的类似, child process中是用MessageBox将收到的字符串显示出来的, 读是用fread()
//



#include "stdafx.h "
#include "windows.h "

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// child process path, 这里你要变一下.
TCHAR szChildPath[MAX_PATH] = TEXT( ".\\child\\debug\\child.exe ");

// message to be passed
const TCHAR msg[] = TEXT( "Hello! Child Console ");
DWORD dwSize = sizeof( msg );

// retrieve the stdin console handle
HANDLE hStdin = ::GetStdHandle( STD_INPUT_HANDLE );
if( hStdin == INVALID_HANDLE_VALUE )
{
::MessageBox(NULL, TEXT( "Can not retrieve stdin "), TEXT( "Error "), MB_OK);
return 0;
}

// create a anonymous pipe to redirect the stdin
SECURITY_ATTRIBUTES sa = {0, 0, TRUE};
HANDLE hReadPipe = NULL, hWritePipe = NULL;
if( !::CreatePipe(&hReadPipe, &hWritePipe, &sa, 0) )
{
::MessageBox(NULL, TEXT( "Can not create pip "), TEXT( "Error "), MB_OK);
::CloseHandle( hStdin );
return 0;
}

// redirect stdin
if( !::SetStdHandle(STD_INPUT_HANDLE, hReadPipe) )
{
::MessageBox(NULL, TEXT( "Can not redirect stdin "), TEXT( "Error "), MB_OK);
::CloseHandle( hReadPipe );
::CloseHandle( hWritePipe );
return 0;
}

// duplicate a non-inheritable handle used to push
// msg into the pipe
HANDLE hWritePipeNonInheritable;

if( ::DuplicateHandle(
GetCurrentProcess(), hWritePipe,
GetCurrentProcess(), &hWritePipeNonInheritable,
0, FALSE, DUPLICATE_SAME_ACCESS ) )
{
::CloseHandle( hWritePipe );
hWritePipe = NULL;
}
else
{
::MessageBox(NULL, TEXT( "Can not duplicate handle "), TEXT( "Error "), MB_OK);
::CloseHandle( hReadPipe );
::CloseHandle( hWritePipe );
::SetStdHandle(STD_INPUT_HANDLE, hStdin);
return 0;
}

// spawn child process
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { sizeof(si) };
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = hReadPipe;

if( !::CreateProcess(
NULL, szChildPath, NULL, NULL, TRUE,
0, NULL, NULL, &si, &pi) )
{
::MessageBox(NULL, TEXT( "Can not spawn child process "), TEXT( "Error "), MB_OK);
::CloseHandle( hReadPipe );
::CloseHandle( hWritePipeNonInheritable );
::SetStdHandle(STD_INPUT_HANDLE, hStdin);
return 0;
}

::CloseHandle( hReadPipe );
hReadPipe = NULL;

// restore stdin
if( !::SetStdHandle(STD_INPUT_HANDLE, hStdin) )
{
::MessageBox(NULL, TEXT( "Can not restore stdin "), TEXT( "Error "), MB_OK);
::CloseHandle( hWritePipeNonInheritable );
return 0;
}

// write to redirected stdin
DWORD dwBytesRead;
::WriteFile(hWritePipeNonInheritable, msg, dwSize, &dwBytesRead, NULL);
::CloseHandle( hWritePipeNonInheritable );

return 0;
}


读书人网 >VC/MFC

热点推荐