在vc++中使用CreateProcess和CreatePipe来执行进程并以字符串形式返回输出
CreateProcess and CreatePipe to execute a process and return output as a string in VC++
我正在尝试使用CreateProcess
和CreatePipe
在Visual Studio 2010中从Windows Forms c++/CLR应用程序中执行进程。
在我的Windows窗体应用程序中,我想执行一个子进程(控制台应用程序),并在我的Windows窗体应用程序中返回std::string
, std::wstring
或System::String^
的输出。此外,我不希望新创建的子进程产生一个窗口。
控制台应用程序是我自己创建的,所以我也可以控制它的源代码。
我已经看到了下面的例子,但是我不明白如何修改代码来完成我想做的事情:
- MSDN
- kgui
- 一个更简单的基于MFC的函数
MSDN代码似乎写成了两个控制台应用程序,一个调用另一个。这代码把我搞糊涂了。我使用c++才4个月左右,所以我还不是完全理解。它似乎引用了一个文本文件,我不需要这样做。
有没有比MSDN的200多行代码或kgui的300多行代码更简单的方法来做到这一点?
这里的答案是有用的,但过于简单。我希望看到一个基本的源代码示例(最好是不涉及数百行复杂代码的示例)。我本来会使用MFC代码,但我很难适应我的目的(我不使用MFC)。
以下是我对code Project中的代码的改编:
string ExecuteExternalFile(string csExeName, string csArguments)
{
string csExecute;
csExecute=csExeName + " " + csArguments;
SECURITY_ATTRIBUTES secattr;
ZeroMemory(&secattr,sizeof(secattr));
secattr.nLength = sizeof(secattr);
secattr.bInheritHandle = TRUE;
HANDLE rPipe, wPipe;
//Create pipes to write and read data
CreatePipe(&rPipe,&wPipe,&secattr,0);
//
STARTUPINFO sInfo;
ZeroMemory(&sInfo,sizeof(sInfo));
PROCESS_INFORMATION pInfo;
ZeroMemory(&pInfo,sizeof(pInfo));
sInfo.cb=sizeof(sInfo);
sInfo.dwFlags=STARTF_USESTDHANDLES;
sInfo.hStdInput=NULL;
sInfo.hStdOutput=wPipe;
sInfo.hStdError=wPipe;
//Create the process here.
CreateProcess(0,(LPWSTR)csExecute.c_str(),0,0,TRUE,NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);
CloseHandle(wPipe);
//now read the output pipe here.
char buf[100];
DWORD reDword;
string m_csOutput,csTemp;
BOOL res;
do
{
res=::ReadFile(rPipe,buf,100,&reDword,0);
csTemp=buf;
m_csOutput+=csTemp;
}while(res);
return m_csOutput;
}
我试过从我的Windows窗体应用程序中使用这个,虽然它编译好,不会引起任何错误,但它似乎也不起作用。我不知道为什么。
我是这样执行上面的代码的:std::string ping = ExecuteExternalFile("ping.exe", "127.0.0.1");
它似乎没有做任何事情,除了在第一次执行时它给出一个非常奇怪的3个字符作为输出,然后在后续执行时,什么也没有。
您没有正确使用::ReadFile()
函数。
阅读这里:http://msdn.microsoft.com/en-us/library/ms891445.aspx
基本上,如果函数不返回TRUE,则希望以错误失败,并且希望继续循环,直到它产生零reDword。
此外,::ReadFile()
不会为您零终止您的数据,所以您必须自己做,像这样:buf[reDword] = ' ';
(确保您的buf
在此之前是101个字符)
由于我被要求提供一些示例代码,这里是,虽然我没有经历实际编译它以确保它工作的麻烦,所以请注意语法错误,并且通常只将其视为应该完成的方向的粗略指针:
#define BUFFER_SIZE 100
string csoutput;
for( ;; )
{
char buf[BUFFER_SIZE+1];
DWORD redword;
if( !::ReadFile(rPipe,buf,BUFFER_SIZE,&redword,0) )
{
DWORD error = ::GetLastError();
//throw new Exception( "Error " + error ); //or something similar
}
if( redword == 0 )
break;
buf[redword] = ' ';
string cstemp = buf;
csoutput += cstemp;
}
return csoutput;
感谢Hans Passant的引导,让我得到了这段清晰简单的代码,这正是我所寻找的。
/// this namespace call is necessary for the rest of the code to work
using namespace System::Diagnostics;
using namespace System::Text;/// added for encoding
Process^ myprocess = gcnew Process;
Encoding^ Encoding;/// added for encoding
Encoding->GetEncoding(GetOEMCP());/// added for encoding
myprocess->StartInfo->FileName = "ping.exe";
myprocess->StartInfo->Arguments = "127.0.0.1";
myprocess->StartInfo->UseShellExecute = false;
/// added the next line to keep a new window from opening
myprocess->StartInfo->CreateNoWindow = true;
myprocess->StartInfo->RedirectStandardOutput = true;
myprocess->StartInfo->StandardOutputEncoding = Encoding;/// added for encoding
myprocess->Start();
String^ output = gcnew String( myprocess->StandardOutput->ReadToEnd() );
myprocess->WaitForExit();
/// OutputBox is the name of a Windows Forms text box in my app.
OutputBox->Text = output;
编辑:添加编码信息。
- 如何保护非托管应用程序中的字符串不受进程转储的影响
- 包含字符串的结构的 Boost 进程间向量是否需要特殊的分配器?
- 读取进程内存无法正常工作,使用 UTF16 字符串
- 提升序列化提升进程间字符串
- 如何从Windows中的进程中读取Unicode字符串
- 写入套接字接收的进程字符串的输入
- GetWindowText 返回另一个进程的空字符串
- 结束进程错误代码 -1,如果访问结构的字符串字段
- 在另一个进程的内存中搜索字符串的每个匹配项
- 如何在另一个进程的内存中搜索字符串
- 将字符串数组传递给多个进程的 for 循环中的 CreateProcess
- 提升没有共享内存的进程间字符串
- 在vc++中使用CreateProcess和CreatePipe来执行进程并以字符串形式返回输出
- 当绕过c++中的函数从目标进程的ExtTextOut复制数据字符串时,malloc会导致崩溃吗?
- 进程快照无法与宽字符串进行比较
- 我如何在另一个进程的内存中通过正则表达式搜索字符串
- 如何保护两个进程之间共享内存中的字符串?
- c++将十六进制写入进程而不是字符串
- 防止将字符串(某些进程)添加到组合框 MFC
- 使用fork在两个进程之间逐字符发送字符串