diff --git a/doc/classes.qbk b/doc/classes.qbk new file mode 100644 index 00000000..d371e2d6 --- /dev/null +++ b/doc/classes.qbk @@ -0,0 +1,116 @@ +[section:class Classes] +[section Child] + +The child class holds a handle to the child process. It can be direclty used to +launch a process via the constructor. It is not copyable, but movable. + +[section Waiting] + +This class does provides three functions to wait for the process to exit. + + wait() + wait_for(duration) + wait_until(time_point); + +If the process exits, the exit_code will be stored inside the class. + +[endsect] + +[section Termination] + +Another way to stop the process is to terminate it. This will also produce an +exit code which is platform-specific. + +[endsect] + +[section Exit Code] + +After a process has exited the exit code is stored either inside the class or the operating +system holds it. The return value of the exit code is undefined if the process did not exit. +The latter can be checked by calling [funcref boost::process::child::is_running is_running]. + +[endsect] + +[endsect] + +[section Pipes] + +The synchronous pipe is implemented as a the template +[classref boost::process::basic_pipe basic_pipe], which can be used with any char type. +The typedefs [classref boost::process::pipe pipe] and [classref boost::process::wpipe wpipe] +provide typedefs for use with char and wchar_t. + +Pipes can be copied, since handles can be duplicated. + +Based on the [classref boost::process::basic_pipe basic_pipe] template, a stream +implementation, similar to the streams in the standard C++ library. + + basic_pstreambuf + basic_pistream + basic_postream + basic_pstream + +[endsect] + +[section Async Pipes] + +The asynchronous pipe class is implemented similar to the I/O objects provided +by boost.asio. + +A async_pipe can be converted into and constructed from a basic_pipe. + +[caution Async pipes use named pipes on windows. Therefore an exception is thrown +if a pipe was not constructed as a named pipe and is converted to an async_pipe] + +[endsect] + +[section Groups] + +The group object is implemented similar to [classref boost::process::child child]. It +does however not provide an exit code. + +[caution A groups behaviour is undefined when it was not used during the launch of a process.] + +[endsect] + + +[section Environment] + +The environment can be stored in two different classes. + + - [classref boost::process::native_environment native_environment] + - [classref boost::process::environment environment] + +This behave simliar to an std::map, in that you can access the variables by the +operator[] with a string key. The returned value is acutally a proxy, which can +be interpreted as a single string or a list of ';' seperated strings. The latter +is used by variables like "PATH". + + +[section Native Environment] + +The [classref boost::process::native_environment native_environment] represents +the current environment. It essentially works like a shared_ptr, though several +copies may not represent the changes done by one. + +``` +native_entironment n1; +native_entironment n2; + +n1["MY_VAR"] = "Thingy"; +n2["MY_VAR"]; //will be empty. +``` + +[endsect] + +[section Environment] + +The plain [classref boost::process::environment environment] class is meant to +be used when starting a new process. It can be constructed from a +[classref boost::process::native_environment native_environment]. + +[endsect] + +[endsect] + +[endsect] \ No newline at end of file diff --git a/doc/design.qbk b/doc/design.qbk new file mode 100644 index 00000000..e05a68fb --- /dev/null +++ b/doc/design.qbk @@ -0,0 +1,42 @@ +[section:design Design Rationale] +[section Scope] +This library is meant to give an wrapper around the different OS-specific methods +to launch processes. Its aim is to provide all functionality that is available on +those systems and allow the user to do all related things, which require using the OS APIs. + +[*This library does not try to provide a full library for everything process related] +In many discussions the proposal was made to build boost.process into a DSEL of some sort. +This is not the goal, it rather provides the facilities to build such a DSEL-Library on top of it. +Therefore the library also does [*not] force any particular use (such as only asynchronous communication) on its user. +It rather could be integrated with such a library. + +[endsect] +[section Interface Style] + +Boost.Process does use a very particular style when constructing a process. +This is because a process holds many properties, which are not members of the actual child class. +Those properties are in many cases not accessible by the father process, for example when using environments. +Here the child process can modify its own environment, but there is no way for the father process to know. +That means, that a child process has properties that cannot be accessed in C++. + +This now leads to the two styles supported and mixed by this library. Overloading and properties. +Consider that you may want to launch a process passing a number of arguments. This is supported in both styles, and would look like this: + +``` +system("gcc", "--version"); //overloading +system("gcc", args={"--version"}); //property style. +``` + +Both styles can also be mixed in some cases. + +``` +system("gcc", "-c", args+={"main.cpp"}); +``` + +In the following documention the avaible styles will be described. Note that the +overload style is implemented via type traits, so the types will be listed. + +[caution There is guarantee in which order the arguments will be executed!] + +[endsect] +[endsect] diff --git a/doc/handbook.qbk b/doc/handbook.qbk new file mode 100644 index 00000000..b37d915c --- /dev/null +++ b/doc/handbook.qbk @@ -0,0 +1,7 @@ +[section:handbook Handbook] + +[include classes.qbk] +[include this_process.qbk] +[include properties.qbk] + +[endsect] \ No newline at end of file diff --git a/doc/process.qbk b/doc/process.qbk index 1da5f5e9..230918cc 100644 --- a/doc/process.qbk +++ b/doc/process.qbk @@ -1,7 +1,7 @@ [library Boost.Process [quickbook 1.5] - [authors [Morgenstern, Klemens]] - [copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 Julio M. Merino Vidal, Ilya Sokolov, Felipe Tanus, Jeff Flinn, Boris Schaeling, Klemens Morgenstern] + [authors [Morgenstern, Klemens David]] + [copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 Julio M. Merino Vidal, Ilya Sokolov, Felipe Tanus, Jeff Flinn, Boris Schaeling, 2016 Klemens D. Morgenstern] [id process] [dirname process] [license @@ -12,6 +12,8 @@ ] [include introduction.qbk] +[include design.qbk] [include tutorial.qbk] +[include handbook.qbk] [xinclude autodoc.xml] [include acknowledgements.qbk] diff --git a/doc/properties.qbk b/doc/properties.qbk new file mode 100644 index 00000000..231e7c5d --- /dev/null +++ b/doc/properties.qbk @@ -0,0 +1,473 @@ +[section Properties] + + +[section Cmd] + + #include + +The cmd property allows to explicitly set commands for the execution. + + system(cmd="gcc --version"); + +For any range or single value the following +expressions are valid: + +``` +//assign +cmd="value"; +cmd(value); + +``` + +The overload form applies when only one string is passed to a launching function. +The string will be internally parsed and split at spaces. +[endsect] + + + +[section Args] + + #include + +The args property allows to explicitly set arguments for the execution. + + system("gcc", args={"--version"}); + +For any range or single value (including std::intializer_list) the following +expressions are valid: + +``` +//assign +args="value"; +args(value); +args={"val1", "val2"}; +args({"val1", "val2"}); + +//append +args="value"; +args={"val1", "val2"}; +``` + +The overload form is used when more than one string is passed, from the second one forward. +I.e. the following expressions are equivalent: + +``` +spawn("gcc", "--version"); +spawn("gcc", args="--version"); +``` + +[note A string will be parsed and set in quotes if it has none and contains spaces.] + +[endsect] + + + +[section Exe] + + #include + +The exe initializer allows to explicitly set arguments for the execution. + + system(exe="gcc"); + +For any range or single value the following +expressions are valid: + +``` +//assign +exe="value"; +exe(value); +``` + +The overload form applies for the first string argument when several string are +passed. It will be used from any position if a boost::filesystem::path is passed. + +[endsect] + + + +[section Shell] + + #include + +The shell property enables to launch a program through the shell of the system. + + system("gcc", shell); + +The shell argument goes without any expression. The operator() is overloaded, to +obtain the path of the system shell. + + auto shell_cmd = shell(); + +[endsect] + + + +[section Error] + + #include + +The error property will set the executor to handle any errors by setting an +error_code. + + std::error_code ec; + system("gcc", error(ec)); + +The overload is achieved by just passing an std::error_code to the function. + +The property has two aliases: + +* `error_ref` +* `error_code` + +[note This will disable the exception.] + +[endsect] + + + +[section Ignore_Error] + + #include + +The ignore_error property will disable any error handling. This can be useful +on linux, where error handling will require a pipe. + +[endsect] + + + +[section Throw_On_Error] + + #include + +The throw_on_error property will enable the exception when launching a process. +It is unnecessary by default, but may be used, when an additional error_code is provided. + +[endsect] + +[section io_service] + + #include + +An io_service must be passed to enable the asynchronous functionality. +It only exists in the explicit form. + +[endsect] + + + +[section on_exit] + + #include + + +When an io_service is passed, the on_exit property can be used, to be notified +when the child process exits. + +``` +io_service ios; +spawn("ls", on_exit=[](int exit, const std::error_code& ec_in){}); +``` + +The following syntax is valid: + +``` +on_exit=function; +on_exit(function); +``` + +[endsect] + +[section I/O] + + #include + +The most complex part in this library is the I/O with the child process. There +are five modes that can be used. + +* File I/O +* Synchronouse Pipe +* Asynchronous Pipe +* Closing +* Redirecting to null + +The properties described here are + +* `std_in` +* `std_out` +* `std_err` + +which should not bee confused with stdin etc. + +Additionally, the output streams can be combined via &, i.e. the following code is valid: + + system("program", (std_out & std_err ) > "log.txt"); + +This property has no overload variant. + +[section File I/O] + +The file I/O simple redirects the stream to a file, where the valid types are + +* `boost::filesystem::path` +* `std::string` +* `const char*` +* `FILE*` + +FILE* is explicitly added, so the process can easily redirect the output stream +of the child to another output stream of the process. That is: + + system("ls", std_out > stderr); + +A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++ +implementation not providing access to the handle. + +The valid expressions for this property are + +``` +std_in < file; +std_in = file; +std_out > file; +std_out = file; +std_err > file; +std_err = file; +(std_out & std_err) > file; +(std_out & std_err) = file; +``` + +Here's an example: + + boost::filesystem::path log = "my_log_file.txt"; + boost::filesystem::path input = "input.txt"; + boost::filesystem::path output = "output.txt"; + system("my_prog", std_out>output, std_inlog); + + +[endsect] + + +[section Synchronous Pipe I/O] + +As explained in the corresponding section, the boost.process library provides a +[classref boost::process::basic_pipe pipe] class which can be used to communicate +with child processes. + +[note Technically the [classref boost::process::async_pipe async_pipe] +works synchronous here, since no asio implementation is used by the library here. +The async-operation will then however not end if the process is finished, since +the pipe remains open. You can use the async_close function with on_exit to fix that.] + +Valid types for pipe I/O are the following: + +* `basic_pipe` +* `async_pipe` +* `basic_ipstream` +* `basic_opstream` +* `basic_pstream` + +Valid expressions with pipes are these: + +``` +std_in < pipe; +std_in = pipe; +std_out > pipe; +std_out = pipe; +std_err > pipe; +std_err = pipe; +(std_out & std_err) > pipe; +(std_out & std_err) = pipe; + +``` + +Note that the pipe may also be used between several processes, like this: + + pipe p; + child c1("nm", "a.out", std_out>p); + chlid c2("c++filt", std_in` [footnote std_out & std_err only] +* `std::future> [footnote std_out & std_err only] + +Valid expressions with pipes are these: + +``` +std_in < buffer; +std_in = buffer; +std_out > buffer; +std_out = buffer; +std_err > buffer; +std_err = buffer; +(std_out & std_err) > buffer; +(std_out & std_err) = buffer; +``` + +[note It is also possible to get a future for std_in, by chaining another `std::future` onto it, i.e. + + std::future fut; + std::string data; + spawn("prog", std_in < buffer(data) > fut); + fut.get(); + ] +[note `boost::asio::buffer` is also available in the `boost::process` namespace.] +[endsect] + +[section Closing] + +Closing a stream means, that no data can be written or read from it. + +This can be achieved by the following syntax. + +``` +std_in < close; +std_in = close; +std_in.close(); +std_out > close; +std_out = close; +std_out.close(); +std_err > close; +std_err = close; +std_err.close(); +(std_out & std_err) > close; +(std_out & std_err) = close; +(std_out & std_err).close(); +``` + +[endsect] + +[section Redirecting to null] + +Unlike closing a pipe, redirecting to null will allow to read and write data. +Written data will disregarded, while read data will only consist of `EOF`. +This can be achieved by the following syntax. + +``` +std_in < close; +std_in = close; +std_in.close(); +std_out > close; +std_out = close; +std_out.close(); +std_err > close; +std_err = close; +std_err.close(); +(std_out & std_err) > buffer; +(std_out & std_err) = buffer; +(std_out & std_err).close(); +``` + +[endsect] + +[endsect] + + + +[section start_dir] + + #include + +To set the start dir, the `start_dir` property is provided. There is no overload format for it. + +It can be used with `std::string` and `boost::filesystem::path`. + +``` +system("ls", start_dir="./bin"); +``` + +[endsect] + + + +[section group] + + #include + +Groups can be used to group processes. There is no guarantee that the launched +process is not also in the same group as the father process. +[note On Posix this is usally the case, while it depends on the group the fathers +process is in on windows. ] + +As an example: + +``` +group g; +child c1("prog1", g); +child c2("prog2", g); + +g.terminate(); //terminate c1 and c2. +``` + +There is no explicit property for this feature. + +[endsect] + + +[section env] + + #include + +The `env` property provides a functional way to modify the environment used by +the child process. If none is passed the environment is inherited from the father +process. Appending means that the environment will be interpreted as a ';' +seperated list as used in PATH. + +The following expressions are valid. + +``` +//assign or create variable +env[NAME] = VALUE; +env[NAME] = {VAL1, VAL2}; +env(NAME, VALUE); +env(NAME, {VAL1, VAL2}); + +//append to variable +env[NAME] += VALUE; +env[NAME] += {VAL1, VAL2}; + +//reset the variable +env[NAME]=boost::none; +env(NAME, boost::none); + +//set the whole environment +env(environment()); +env=environment(); + +``` + +As an example: + +``` +spawn("b2", env["PATH"]+="F:/boost", env["SOME_VAR"]=boost::none, env["NEW_VAR"]="VALUE"); +``` + +The overload style is done by passing an instance of [classref boost::process::environment environment]. +The above example would look like this. + +``` +environment e = this_process::environment(); +e["PATH"] += "F:/boost"; +e.erase("SOME_VAR"); +e["NEW_VAR"] = "VALUE"; +spawn("b2", e); +``` + +[caution Passing an empty environment will cause and error.] + +[endsect] + + +[endsect] \ No newline at end of file diff --git a/doc/this_process.qbk b/doc/this_process.qbk new file mode 100644 index 00000000..5383e267 --- /dev/null +++ b/doc/this_process.qbk @@ -0,0 +1,33 @@ +[section:this_process this_process] + +Similar to std::this_thread, the boost::process library provides a +boost::this_process namespace which allows to obtain and modify the property of +the current process. + +It provides the following functions. + +Get the process id of the current process. + + int get_id(); + +Get the native handle of the current process. + + native_handle_t native_handle(); + +Get the enviroment of the current process. + + native_environment environment(); + +Get the path environment variable of the current process runs. + + std::vector< std::string > path(); + +Get the print working directory of the current process. + + std::string pwd(); + +Get the current working directory of the current process. + std::string cwd(); + + +[endsect] \ No newline at end of file diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 2e448099..a1cc6928 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -13,170 +13,125 @@ Boost.Process is a header-only library. It comes with a convenience header file [section Starting a program] -The function Boost.Process provides to start a program is [funcref boost::process::execute execute]. The parameter list is built automatically from a variadic argument list. Some need to be used with initializers, but strings are determined automatically as commands. + #include + +To start a process in the regular way, the construction of a [classref boost::process::child], which will automatically launch a child process. [import ../example/execute.cpp] [execute] -The same goes for boost::filesystem::path. +There are three possibilities to launch a process in boost.process. -[execute_path] +[section Child] -Boost.Process provides two utility functions to lookup executables: Call [funcref boost::this_process::path path] if you want to find an executable in the directories of the environment variable PATH. Or call [funcref boost::this_process::path shell_path] for the system's shell. +The standard version is to create a child, which will spawn the process. + + child c("ls"); + +This will create an attached child process. [endsect] -[section Resources] +[section System] -Boost.Process implements the RAII Principle similar to std::thread. That is, the execute function returns a child which handles the resources of a the subprocess. By default, the desctructor of child will wait for the subprocess to exit. +As a convenience, the [funcref boost::process::system] function is provided. It works as std::system, though it allows +all the properties boost.process provides. It will execute the process and wait for it's exit; then return the exit_code. -[import ../example/cleanup.cpp] -[cleanup] - -This behaviour may be changed at runtime by calling [funcref boost::proces::child::detach detach]. After detaching a process will survive the destruction of the child. - -[cleanup_detach] - -This of course allows a short-cut syntax: - -[cleanup_detach_short] - -Unlike std::thread, a terminate is also available: - -[import ../example/terminate.cpp] -[c_terminate] + int ret = system("ls"); + +[caution When used with Pipes it will almost always result in a dead-lock.] [endsect] -[section Handling errors] +[section Spawn] -Boost.Process provides three methods to detect errors: ignoring, set an error_code, throwing an error. The implementations for error handling is included in [headerref boost/process/error.hpp] +Another function which is more then convenience is the [funcref boost::process::spawn] function. +This function starts a process and immediately detaches it. It also prevents the system from creating a zombie process. -By default (i.e. not provided error handler) the latter one is used, i.e. an instance of std::system_error is thrown. - -If the error_code shall be used, a reference to std::error_code must be passed to the execute function. - -[import ../example/error_handling.cpp] -[set_on_error] - -If no error shall be handled boost::process::ignore_error can be passed to execute. - -[ignore_error] - -Use [classref boost::process::initializers::throw_on_error throw_on_error] if you want [funcref boost::process::execute execute] to throw an exception: - - -[note On POSIX the error is handled via a pipe, except if ignore_error is passed. If `execve` fails the initializers send *errno* through a pipe from the child to the parent process. The pipe is automatically closed no matter whether `execve` succeeds or fails.] + spawn("ls"); + +[caution There is no guarantee that the child process will survive the father process terminating. This is dependant on the Operating System.] [endsect] - -[section Starting in a specific work directory] - -Use the initializer [classref boost::process::start_dir start_dir] to set the work directory: - -[import ../example/work_dir.cpp] -[work_dir] - -[classref boost::process::start_dir start_dir] also supports [classref boost::filesystem::path]. - -For portability reasons you want to use an absolute path with [classref boost::process::initializers::run_exe run_exe] if you set the work directory with [classref boost::process::initializers::start_in_dir start_in_dir]: - -[work_dir_abs] - -On Windows a relative path is relative to the work directory of the parent process. On POSIX a relative path is relative to the work directory set with [classref boost::process::initializers::start_dir start_dir] as the directory is changed before the program starts. - -[tip Use an absolute path with the binary to run if you set the work directory with [classref boost::process::initializers::start_dir start_dir] to avoid portability problems.] - [endsect] -[section Environment variables] +[section Arguments/Command Style] -Boost.Process provides faculties to modify the environment. By default the environment is inherited. It may be obtained by [funcref boost::this_process::environment] which stores it in the type [classref boost::process::native_environment] sharing the state of the environment of the current process with all other instances. This object may be copied into an instance of [classref boost::process::environment] which can be passed to [funcref boost::process::execute]. +When passing arguments to the process, two styles are provided, the cmd-style and the exe-/args-style. -[import ../example/env.cpp] -[modifiy_env] +The cmd style will interpret the string as a sequence of the exe and arguments and parse them as such, while the exe-/args-style will +interpret each string as an argument. -Additionally the [classref boost::process::env] parameter may be used to modify the environment inside the execute call. +[table:id Cmd vs Exe/Args + [[String] [Cmd] [Exe/Args]] + [["gcc --version"] [{"gcc", "--version"}] [{"\\"gcc --version\\""}]] +] -[inherit_env] +When using the overloading variant, a single string will result in a cmd interpretation, several strings will yield a exe-args interpretation. Both version can be set explicitly: -[endsect] +``` +system("grep -c false /etc/passwd"); //cmd style +system("grep", "-c", "false", "/etc/passwd"); //exe-/args- -[section I/O ] - -All I/O is concetrated in three parameters: - - * std_in - * std_out - * std_err - -They allow the following operations for each stream: - - * redirecting to file/pipe/null - * implicit asynchronous operations - * closing - -std_out and std_err may be combined via &. - -[section Redirection] - -Closing can be done the following way. - -[import ../example/io.cpp] -[close] - -Redirecting to null can be done in the following way. - -[null] - - -Redirecting to files may be done via file_descriptors, filenames (as strings or boost::filesystem::path) and FILE*. - -[redirect] +system(cmd="grep -c false /etc/passwd"); //cmd style +system(exe="grep", args={"-c", "false", "/etc/passwd"}); //exe-/args- +``` [endsect] [section Synchronous I/O] -Synchronous I/O may be done via pipes, as shown in the example. The sink/source are implemented via boost::iostreams::file_descriptor, so they can be put into a stream. +The simplest way to communicate with a child-process is via pipes. -[pipe] +``` +opstream in; +ipstream out; -[endsect] +child c("c++filt", std_out > out, std_in < in); -[section Asynchrounous I/O] +in << "_ZN5boost7process8tutorialE" << endl; +std::string value; +out >> value; +c.terminate(); +``` -To enable asynchronous I/O the library needs boost.asio. Therefor a pipe class [classref boost::process::async_pipe] is provided which implements the properties to use it as an I/O Object for boost.asio. It is recommended to connect the async_close function to on_exit on initialization, so the pipe is closed when the process exits. The async_close function posts the close request in the io_service, so the current operation is finished. - -[async_pipe] - -For simple operations (i.e. writing one buffer, reading one buffer), a lazy syntax can be used. For convenience [funcref boost::asio::buffer] function is also available in -[funcref boost::process::buffer] - -[async_pipe_simple] - -Additionally, the values may be redirected to a std::future. - -[async_pipe_future] - -[endsect] - -[endsect] - - -[section Waiting for a program to exit] - -Call [funcref boost::process::wait_for_exit wait_for_exit] to wait for a program to exit: - -[import ../example/wait.cpp] -[sync] - -When working with an [classref boost::asio::io_service] the process may wait asynchrounously for the exit of the process. This allows the usage of the on_exit initializer. - -[async] +[caution This comes with the danger of dead-locks, so it should be used with care.] [endsect] +[section Asynchronous I/O] + +Boost.Process provides capacities to communicate in an asynchronous way using Boost.Asio. +To do that, the [classref boost::process::async_pipe async_pipe] class is provided, which can be used +as an I/O object directly: + +``` +asio::io_service ios; +async_pipe pipe; +spawn("ls", std_out > pipe, ios); + +std::string buf; + +boost::asio::async_read(p, buffer(buf), + [](const boost::system::error_code &ec, std::size_t size){}); + +ios.run(); +``` + +The library also provides a shortcut for this: + +``` +asio::io_service ios; + +std::string buf; + +spawn("ls", std_out > buffer(buf), ios); + +ios.run(); +``` + +[endsect] + [endsect] diff --git a/doc/windows.qbk b/doc/windows.qbk index 0f74d9cc..a348759a 100644 --- a/doc/windows.qbk +++ b/doc/windows.qbk @@ -1,6 +1,6 @@ [section Windows specifics] -[section Setting wShowWindow] +[section Setting show_window] Use the initializer [classref boost::process::initializers::show_window show_window] to set the member variable `wShowWindow` in [@http://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx `STARTUPINFO`]: @@ -11,10 +11,9 @@ Use the initializer [classref boost::process::initializers::show_window show_win [section Unicode] -Boost.Process supports Unicode on Windows. If the macro [macroref UNICODE] or `_UNICODE` is defined, the Unicode version of [@http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx `CreateProcess`] is used: - -[import ../example/windows_unicode.cpp] -[unicode] +Boost.Process does currently NOT support UNICODE on windows. +Using wchar_t is not supported on posix, and would thus break the api. +In later versions the windows implementation may be changed to use a codecvt underneath. [endsect] diff --git a/example/error_handling.cpp b/example/error_handling.cpp index f63c333c..d0b5a116 100644 --- a/example/error_handling.cpp +++ b/example/error_handling.cpp @@ -17,10 +17,10 @@ int main() { //[set_on_error std::error_code ec; - execute("test.exe", ec); + child c("test.exe", ec); //] //[ignore_error - execute("test.exe", ignore_error); + child c("test.exe", ignore_error); //] } diff --git a/example/execute.cpp b/example/execute.cpp index 954c6894..713d6007 100644 --- a/example/execute.cpp +++ b/example/execute.cpp @@ -10,16 +10,15 @@ #include using namespace boost::process; -using namespace boost::process::initializers; int main() { //[execute - execute("test.exe"); + child c("test.exe"); //] //[execute_path boost::filesystem::path exe = "../test.exe"; - execute(exe); + child c(exe); //] } diff --git a/example/intro.cpp b/example/intro.cpp index 8eebd3ba..3516cbec 100644 --- a/example/intro.cpp +++ b/example/intro.cpp @@ -14,7 +14,7 @@ using namespace boost::process; int main() { - pstream pipe_stream; + ipstream pipe_stream; system("gcc.exe", "--version", std_out > pipe_stream);