How do I get the output of a sub process and assign it to a variable. EG: assign the output of wmic csproduct get uuid
returns a long string of characters in CMD, how would I run that command in C++ and assign it to a variable?

- 13
- 3
-
1**Reopened** after the question was closed as a duplicate of a Posix question. This question is tagged "winapi". The Windows API is not Posix-compliant. – Cheers and hth. - Alf Nov 11 '16 at 07:25
2 Answers
There are two main options for capturing the output of a process:
- Redirect it to a file, then read the file later.
- Use a pipe.
Pipes are not supported by the standard library, other than hidden behind the common stream abstraction. Effectively that means that a process A that creates a process B, can't communicate with B via pipes, unless platform-specific functionality for that is used. In Windows the scripting support, Windows Script Host, has direct functionality for the pipe approach, based on polling for output from B. At a much lower level you can use the CreateProcess
API function. But it's not trivial to do.
With a temporary file as communication channel, and using only standard C++ functionality, you simply invoke program B via a command interpreter that can redirect B's output. This command interpreter and its syntax then constitutes the platform specific part. So even this approach is platform specific, but the C++ code as such is portable.
In Windows the standard command intepreter is cmd.exe
, and it uses the ordinary Unix >
syntax in order to redirect output of a program, so the command to be executed can be like
cmd /c "b.exe >tempfile"
You can execute such a command via C++ system
. The system
function already executes the specified command via a command intepreter, which in Windows is cmd.exe
. And so the argument to system
only needs to be
b.exe > tempfile
where tempfile
is the name or full path to the file where you want the result.
You can create a fresh temporary filename via the tmpnam
function.

- 142,714
- 15
- 209
- 331
-
1Using system is a terrible way to do this. If you really want to send out to a file, create a file and pass it when calling CreateProcess. Invoking cmd just to redirect output is somewhat needless. – David Heffernan Nov 11 '16 at 19:35
-
@DavidHeffernan: In Windows `system` is just a wrapper for invoking `CreateProcess`. One good reason to use `CreateProcess` directly could be that one is running a console subsystem program from a process that currently has no associated console window, and does not want a console window to flash or show on the screen. But without such a reason, in general, it would be silly to reinvent that wheel. `system` is there in the standard library because it does the job, very nicely. It's not "terrible" in any way. – Cheers and hth. - Alf Nov 11 '16 at 20:10
-
Since you give no reason I have to guess, and I ***guess*** that you're concerned with efficiency. However, the main contributor to the time here is the running of the started process: its output (which is slow as molasses compared to typical internal C++ operations), and its use of other helper processes (especially `wmic` has a habit of starting such). And so spending time on going down to the Windows API level, using `CreateProcess`, on those grounds, would just be premature optimization. – Cheers and hth. - Alf Nov 11 '16 at 20:12
-
I don't see why we need another process to do what can be done directly. – David Heffernan Nov 11 '16 at 20:17
-
@DavidHeffernan: Just for simplicity. Which can translate to an hour's (saved) work or so for this, including testing. Or ten minutes for me and you, maybe. But enough. :) If **measurements** show that extra `cmd.exe` process to be a bottleneck, then it can, in my opinion, be reasonable to start thinking about spending some time on optimizing the thing. – Cheers and hth. - Alf Nov 11 '16 at 20:19
-
There are plenty of arguments against using system. http://stackoverflow.com/questions/2923843/can-i-use-boost-library-for-crossplatform-application-executing/2925579#2925579 is one of many. I'd just call CreateProcess like a grown up..... – David Heffernan Nov 11 '16 at 21:36
-
Very dated FUD. E.g. there is no `command.com` in modern Windows, and hasn't been since the 1990's. Don't use SO as an authority: in at least 50% of cases that's akin to using Herb Schildt as authority. So, don't be afraid of using `system`. Happy. :) – Cheers and hth. - Alf Nov 11 '16 at 22:10
-
I assume the winapi tag is referring to the answer you need and it also hints to the platform. So, I think the answer is _popen
Example:
#include <stdio.h>
int main()
{
FILE* CommandResult = _popen("wmic csproduct get uuid", "rt"); //send the command to the cmd and return a pointer to the command result
char line[256]; //a buffer to read from the file
while(fgets(line, 256, CommandResult)) printf(line); //read and print all lines one by one
_pclose(CommandResult);
scanf(line); //prevent the console from closing immediately
}
Edit:
I just realized that I must attach the following disclaimer with any line of code before I can publish it.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

- 44
- 5
-
It would be even better (consultant-speak) to (1) check for failures, and to (2) note that `_popen` is a common vendor extension to the runtime library on the Windows platform, but is not part of the Windows API. And (3) fix the `printf`, which for some inputs has UB. Also, (4) to omit the negative utility `scanf` at the end: it has no advantage, it's very much a practical hindrance in many situations, and for some (admittedly not the most likely) inputs it has UB. Since the question is tagged C++, not C, a further improvement could be to (5) present conventional C++ code, not pure C code. – Cheers and hth. - Alf Nov 11 '16 at 09:56
-
Possibly you need a concrete example. Here is one: the command picks up a `wmic` in the current directory, made for testing purposes. Its output is `%s`. The `printf` then tries to access a non-existing argument. Its behavior is undefined in this case. A likely result is some garbage output and a crash. – Cheers and hth. - Alf Nov 11 '16 at 11:02
-
Valid C code is not necessarily valid C++ code. Besides that, Cheers and hth. - Alf raises valid points. If you feel like you don't care about reputation, then at least respect others that do (like myself). You have two options: Fix your answer, or delete it. Either way it gives down voters a chance to get their reputation back. – IInspectable Nov 11 '16 at 12:39
-
Peculiarly, [MSDN example for _popen](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen) has the same idea but does not get so many things wrong at once. – YellowAfterlife Jan 27 '20 at 12:13