1. popen(可获取命令行执行后的输出结果)
概述
popen()
可以执行shell命令,并读取此命令的返回值;
popen()
函数通过创建一个管道,调用fork()
产生一个子进程,执行一个shell以运行命令来开启一个进程。可以通过这个管道执行标准输入输出操作。这个管道必须由pclose()
函数关闭, 而不是fclose()函
数(若使用fclose
则会产生僵尸进程)。pclose()
函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose()
返回的终止状态与shell已执行exit一样。
函数原型
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
type
参数- 只能是读或者写中的一种,得到的返回值(标准I/O流)也具有和type相应的只读或只写类型。
- 如果type是”r”则文件指针连接到command的标准输出;
- 如果type是”w”则文件指针连接到command的标准输入。
command参数
- 是一个指向以NULL结束的shell命令字符串的指针。这行命令将被传到bin/sh并使用-c标志,shell将执行这个命令。
返回值
- 如果调用
fork()
或pipe()
失败,或者不能分配内存将返回NULL
,否则返回标准I/O流。 popen()
没有为内存分配失败设置errno值。- 如果调用
fork()
或pipe()
时出现错误,errno被设为相应的错误类型。 - 如果type参数不合法,**errno将返回EINVA**L。
- 如果调用
例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
void print_result(FILE *fp)
{
char buf[100];
if(!fp)
{
return;
}
printf("\n>>>\n");
while(memset(buf, 0, sizeof(buf)), fgets(buf, sizeof(buf) - 1, fp) != 0 ) {
printf("%s", buf);
}
printf("\n<<<\n");
}
int main(void)
{
FILE *fp = NULL;
while(1) {
fp = NULL;
fp = popen("ls", "r");
if(!fp) {
perror("popen");
exit(EXIT_FAILURE);
}
print_result(fp);
pclose(fp);
sleep(1);
}
}
2. 使用Windows API的管道(可获取命令行执行后的输出结果,功能比2强大)
- 使用匿名管道和
CreateProcess
函数实现不弹出黑框,获取命令行执行后输出结果 - 使用
CreateProcess
可以设置命令行启动信息、 可以指定命令行执行的目录等等
std::wstring Connection::ExeCmd(std::wstring pszCmd)
{
// 创建匿名管道
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
HANDLE hRead, hWrite;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
{
return TEXT(" ");
}
// 设置命令行进程启动信息(以隐藏方式启动命令并定位其输出到hWrite
STARTUPINFO si = {sizeof(STARTUPINFO)};
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdError = hWrite;
si.hStdOutput = hWrite;
// 启动命令行
PROCESS_INFORMATION pi;
if (!CreateProcess(NULL, (LPWSTR)pszCmd.c_str(), NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))
{
return TEXT("Cannot create process");
}
// 立即关闭hWrite
CloseHandle(hWrite);
// 读取命令行返回值
std::string strRetTmp;
char buff[1024] = {0};
DWORD dwRead = 0;
strRetTmp = buff;
while (ReadFile(hRead, buff, 1024, &dwRead, NULL))
{
strRetTmp += buff;
}
CloseHandle(hRead);
LPCSTR pszSrc = strRetTmp.c_str();
int nLen = MultiByteToWideChar(CP_ACP, 0, buff, -1, NULL, 0);
if (nLen == 0)
return std::wstring(L"");
wchar_t* pwszDst = new wchar_t[nLen];
if (!pwszDst)
return std::wstring(L"");
MultiByteToWideChar(CP_ACP, 0, pszSrc, -1, pwszDst, nLen);
std::wstring strRet(pwszDst);
delete[] pwszDst;
pwszDst = NULL;
return strRet;
}