2014-10-12 202 views
3

我有这样的代码:如何将system()函数的输出重定向到变量?

system("echo %username%"); 

我想它的结果重定向到一个变量,说uname

我该怎么办呢?

我知道WinAPI,但我想这样做。

+0

您需要['pipe'](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365152 (v = vs.85).aspx) – 2014-10-12 10:29:22

+0

如果您需要的是用户名,请考虑使用操作系统本机接口。 'system'不仅不安全,而且还有_slow_(产生一个新的进程等)。如果您坚持重复使用另一个进程,请尝试使用['pipe'](http://linux.die.net/man/2/pipe)。无法检索用'system'调用的命令的输出。 – Kalrish 2014-10-12 10:31:16

+0

好的,那么对于系统(“systeminfo”);输出大的地方,我如何将它重定向到文本文件? – blah 2014-10-12 10:34:24

回答

2

快速,丑陋和肮脏的方法是将输出重定向到一个文件,然后读取该文件。

system("echo %username% > someFile.txt"); 

一个更精细的方式是使用CreateProcess API使用以下命令行:cmd.exe /c echo %username%

该API允许您指定自定义的标准输入和标准输出。您可以为标准输出创建管道,如下所示:

HANDLE g_hChildStd_OUT_Wr = NULL; 

SECURITY_ATTRIBUTES saAttr; 

saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
saAttr.bInheritHandle = TRUE; 
saAttr.lpSecurityDescriptor = NULL; 

// Create a pipe for the child process's STDOUT. 
// 
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) return -1; 

然后在CreateProcess API中使用此管道。事情是这样的:

TCHAR szCmdline[]=TEXT("cmd.exe /c echo %username%"); 
PROCESS_INFORMATION piProcInfo; 
STARTUPINFO siStartInfo; 

// Set up members of the PROCESS_INFORMATION structure. 
// 
memset(&piProcInfo, 0, sizeof(PROCESS_INFORMATION)); 

// Set up members of the STARTUPINFO structure. 
// This structure specifies the STDIN and STDOUT handles for redirection. 
// 
memset(&siStartInfo, 0, sizeof(STARTUPINFO)); 
siStartInfo.cb = sizeof(STARTUPINFO); 
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; 
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 

再从管道中读取像这样的东西:

DWORD dwRead, dwWritten; 
CHAR chBuf[BUFSIZE]; 
BOOL bSuccess = FALSE; 
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 

for (;;) 
{ 
     bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL); 
     if(! bSuccess || dwRead == 0) break; 
} 

所以你需要知道什么时候该进程结束,做适当的清理将异步运行的进程。因此,为了完成这项工作,需要在这里学习一些细节。

一个完整的例子可以在这里找到: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx

+0

由于我的程序做了很多日志记录,我更喜欢肮脏的方式。谢谢。 – blah 2014-10-12 11:22:29

+1

使用'system'将数据输出到文件中没有什么不好看的。可用命令以及命令字符串的解释方式取决于您正在运行的系统,但如果这对您的应用程序不是问题,那么'system'是一个非常好的解决方案。 – 2014-10-12 11:35:59

+0

当我说丑陋和脏兮兮的时候有些夸张,但原因是这个方法有一些限制,因为不是所有的东西都可以通过在最后加入“> file.txt”很好地重定向,它涉及创建一个文件这也有一些后勤问题:命名文件,稍后删除文件等。 – 2014-10-12 11:52:06

0

如果目标仅仅是获得用户名,你有没有考虑getenv; getenv("username")将直接返回它。

否则,如果你有更多的,你想做的事,并希望在一个文件中的结果...你传递给system的字符串传递给命令解释器,所以任何你可以做在命令行中cmd.exe将在system中工作:文件重定向,管道到另一个进程等。