我需要执行一个程序并在c ++中检索它的stdout输出.我希望我的代码也是跨平台的.
最近我发现了针对您所有跨平台需求的Boost c ++库的精彩世界,我想我会去boost.org并阅读Boost.Process的文档.令我惊讶的是,它不存在!然后我开始弄清楚Boost给他们的跨平台库启动外部进程的名称,但到目前为止还没有找到它.
谷歌搜索带我去了Julio M. Merino Vidal的Boost.Process,它似乎是我正在寻找的非官方Boost库.奇怪的是,我似乎无法在该网站上找到下载链接.似乎该项目最近没有任何进展.
我终于能够在外部网站上找到Vidal的Boost.Process的下载链接,并且现在将使用它,但是我非常惊讶于我需要付出的努力才能获得跨平台的c ++库.与外部流程互动.
那么,为什么没有正式的Boost.Process?这似乎是一个非常有价值的补充.或者我完全忽视了这里明显的解决方案?您是否可以建议其他跨平台库来管理外部流程的简单启动和交互?
我尝试使用CreateProcess来运行一个简单的命令hg > test.txt.我尝试将字符串作为一个整体运行(而不是将其分成应用程序名称及其参数).为什么CreateProcess(0, "notepad.exe test.txt", ...)工作但CreateProcess(0, "hg > test.txt", ...)不工作?
我在Visual Studio中有一个C++项目,并且已经添加了另一个专门用于测试的项目.这两个项目都是EXE(控制台应用程序).那么如何在第二个项目中使用第一个项目呢?
只是为了澄清一下,如果第一个项目是一个可以简单地包含在第二个项目中的库,那么这里的问题就不言而喻了,但作为一个EXE,这就是问题所在.
我正在使用CreateProcess()从我的GUI应用程序在Windows中运行外部控制台应用程序.我想以某种方式收集输出,以了解是否有错误.现在我知道我必须用hStdOutput做一些事情,但我不明白是什么.我是c ++和没有经验的程序员的新手,我实际上不知道如何处理句柄或如何点亮管道.
如何将输出转换为某种变量(或文件)?
这就是我现在所拥有的:
void email::run(string path,string cmd){
WCHAR * ppath=new(nothrow) WCHAR[path.length()*2];
memset(ppath,' ',path.length()*2);
WCHAR * pcmd= new(nothrow) WCHAR[cmd.length()*2];
memset(pcmd,' ',cmd.length()*2);
string tempstr;
ToWCHAR(path,ppath); //creates WCHAR from my std::string
ToWCHAR(cmd,pcmd);
STARTUPINFO info={sizeof(info)};
info.dwFlags = STARTF_USESHOWWINDOW; //hide process
PROCESS_INFORMATION processInfo;
if (CreateProcess(ppath,pcmd, NULL, NULL, FALSE, 0, NULL, NULL, &info, &processInfo))
{
::WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
delete[](ppath);
delete[](pcmd);
}
Run Code Online (Sandbox Code Playgroud)
这段代码可能让任何体面的程序员尖叫,但(我甚至不应该说:)它的工作原理;-)
问题:如何使用hStdOutput读取文件的输出(例如)?
背景:
我的工作需要能够捕捉程序stdout,stderr并返回程序的值.理想情况下,我想在我存储在我的对象中的字符串中捕获这些字符串,该字符串包含进程的详细信息.我目前有一些代码,通过使用一些(在我看来)古老的C文件句柄魔术将输出保存到文件中.任何时候我想输出结果,我打开该文件,然后打印内容.
有时(当我生成的进程继续运行时)我的可执行文件的下一次执行将会中断,因为它无法打开文件进行写入.
问题陈述:
我正在寻找一种方法来将stdout窗口中创建的进程的输出保存为一个字符串,并stderr以更安全,更现代的方式保存到另一个字符串.这样我就可以在每次输出每个创建过程的结果时打印这些内容.
我丑陋的代码:
主要块 -
int stdoutold = _dup(_fileno(stdout)); //make a copy of stdout
int stderrold = _dup(_fileno(stdout)); //make a copy of stderr
FILE *f;
if(!fopen_s(&f, "name_of_my_file", "w")){ //make sure I can write to the file
_dup2(_fileno(f), _fileno(stdout)); //make stdout point to f
_dup2(_fileno(f), _fileno(stderr)); //make stderr point to f
fork("command_I_want_to_run", &pi); //run my fake fork (see below)
}
else{
...//error handling
}
_close(_fileno(stdout)); //close tainted stdout
_close(_fileno(stderr)); //close …Run Code Online (Sandbox Code Playgroud) 我正在使用CreateProcess启动交互式脚本解释器,并希望透明地将stdin/stdout/stderr转发给解释器.
我的第一次尝试是设置STARTUPINFO传递给CreateProcess喜欢的结构
STARTUPINFOA si = { sizeof( si ) };
si.hStdError = ::GetStdHandle( STD_ERROR_HANDLE );
si.hStdOutput = ::GetStdHandle( STD_OUTPUT_HANDLE );
si.hStdInput = ::GetStdHandle( STD_INPUT_HANDLE );
si.dwFlags |= STARTF_USESTDHANDLES;
Run Code Online (Sandbox Code Playgroud)
即我试图让脚本解释器进程使用与我的启动程序进程使用的读/写相同的句柄.这似乎不起作用(我甚至不确定那些标准句柄是否可以继承).
基于创建具有重定向输入和输出的子进程示例的第二个想法是设置三个管道以转发写入任何管道的所有数据.由于我不知道如何等待数据写入多个文件(WaitForMultipleObjects无法在管道上同步),我考虑有三个线程,每个线程ReadFile在管道上进行阻塞调用.
我怀疑这可能有点矫枉过正,所以我想知道:有更简单的方法吗?我根本不需要对从脚本解释器传递的数据进行任何处理.
作为旁注,在Linux上我只是用execvp脚本解释器进程替换当前进程,但在Windows上我需要启动脚本解释器,主线程处于挂起状态(这样我就可以进行一些字节码修补) - 所以即使因为_execvp似乎可以在Windows上使用,我显然必须使用CreateProcess.