What is the equivalent to Posix popen() in the Win32 API?
Asked Answered
F

5

35

Is there a rough equivalent to the Linux/Unix stdio.h popen() function in the Win32 API? If so, where can I find it?

Edit: I need to know this to patch an omission in the D standard library. Any answer must use only standard Win32 API, no MSVC-specific functions. Also, I'd prefer something that's not horribly low-level, if it exists.

Faugh answered 16/1, 2009 at 15:54 Comment(3)
_popen is part of the standard C library on Windows and is available to anyone linking against/using the standard C library.Bilection
Ok, well I couldn't seem to get it working from D, which supports the C ABI, but that's probably beyond the scope of this question.Faugh
Windows is not Linux; there is no standard C library in the OS. KERNEL32.DLL does not have printf()Burton
M
27

MSDN explains how you do what popen does using the Windows API in Pipe Handle Inheritance . Here it provides a well-documented example. It's way more low-level than the _popen function found in the runtime library linked by Jason, but uses the Win32 API exclusively.

Maybellmaybelle answered 16/1, 2009 at 16:12 Comment(3)
Oh, I like this answer much better than mine :)Bilection
It looks very interesting, and had I not been 2 days late on my delivery deadline, I might be interested in implementing this solution :-) . But for my needs (I just want to capture stdout), _popen is more than enough.Trickle
did you forget to post a link to the MSDN page? Where is this well-documented example?Alten
B
22

You can call _popen if you're writing a console application. For more information, see the documentation on the MSDN site: http://msdn.microsoft.com/en-us/library/96ayss4b(VS.80).aspx

Bilection answered 16/1, 2009 at 16:7 Comment(2)
i like your's too, mate. fits directly what that guy wants i think :)Maybellmaybelle
Be aware that this doesn't handle spaces in the path :(Fantastically
U
3

Sadly it's not particularly easy.

You need to create a pipe using the win32 function (CreatePipe), then typically you need to duplicate the end of the pipe (DuplicateHandle) that you're giving to the subprocess to allow it to be inherited, otherwise it won't be and hence can't be used.

Then you need to create a process using CreateProcess (which takes lots of structure pointers, including a STARTUPINFO), and pass in the STARTUPINFO the handle that you've duplicated as its stdout.

Then you can read from the reading end of the pipe (ReadFile etc) until you reach eof, then you need to clean up by closing all the various win32 handles.

Ugrian answered 19/1, 2009 at 21:38 Comment(0)
F
3

Digging up an old thread ...

Reacting to Jason Coco's reply above, and contrary to what the linked MSDN page claims, it is apparently possible nowadays to call _popen() from non-console apps. I call it from a QuickTime importer component, basically a DLL in disguise. It opens a console window but otherwise shows the expected behaviour. Compiling a standard console tool with mingw32's -mwindows option to make it a GUI app, _popen continues to work correctly (but a console window opens even when running the tool from another console.

Fenton answered 27/11, 2012 at 1:49 Comment(0)
C
1

This is an old post, but I also had a need several years ago to use a popen() like call in a Windows environment. As several of the comments in the answer here have noted, using the Windows API to implement anything close to the classic POSIX popen() is interesting.

I created an implementation which I submitted to Code Review . This implementation uses pipes to stdin and from stdout, as well as Windows methods for CreateProcess(...).

The linked code is designed to be built into a dll with a very small API.

int __declspec(dllexport) cmd_rsp(const char *command, char **chunk, unsigned int size); 

Simple example of usage:

#include "cmd_rsp.h"
int main(void)
{
    char *buf = {0};
    buf = calloc(100, 1);
    if(!buf)return 0;
    cmd_rsp("dir /s", &buf, 100);
    printf("%s", buf);
    free(buf);
    //or a custom exe
    char *buf2 = {0};
    buf2 = calloc(100, 1);
    cmd_rsp("some_custom_program.exe arg_1 arg_2 arg_n", &buf2, 100);
    printf("%s", buf2);
    free(buf2);
    
    return 0;
}

It takes any command that can be for example issued from stdin, creates a separate process to execute the command, then returns all response content (If there is any) to a buffer, and does this without displaying the CMD window popup. The buffer grows as needed to accommodate size of response.

Cogitation answered 16/9, 2020 at 18:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.