Boost::process 如何在 Windows 上隐藏控制台窗口

8
最近发布了boost 1.64,其中包括boost::process。它提供了一个易于使用的界面来启动进程。以前我使用过独立版本的boost::process库(请参见此处)。这很有效。我想转换到新版本,以便可以取消独立库的依赖。
API有一点不同,但是一切都正常工作,除了一个问题。在旧版本中,我能够传递一个Windows特定的上下文对象,允许我隐藏任何由进程打开的控制台窗口。
boost::process::win32_context ctx;
ctx.environment = boost::process::self::get_environment();

STARTUPINFOA stup;
ZeroMemory(&stup, sizeof(stup));
stup.cb = sizeof(stup);
stup.dwFlags = STARTF_USESHOWWINDOW;
stup.wShowWindow = SW_HIDE;
ctx.startupinfo = &stup;

std::vector<std::string> args;
boost::process:child process = boost::process::win32_launch("myprogram", args, ctx);

使用新版本后,它的样子是这样的:
boost::process::environment env = boost::this_process::environment();
boost::process:child process(boost::filesystem::path("myprogram"), env);

除了隐藏控制台窗口外,一切工作正常。是否有可能实现这一点?
2个回答

10

child 构造函数接受一个类型列表,稍后将使用 ::boost::fusion 方法将其转换为一系列调用,执行实际的初始化。因此,您可以按任意顺序推送支持的类型参数:

#include <boost/process.hpp>
#include <boost/process/windows.hpp> // for windows::hide that can only be used on Windows

...

::boost::process::environment env = ::boost::this_process::environment();
::boost::process::child ch1("cmd", env, ::boost::process::windows::hide); // ok
::boost::process::child ch2(::boost::filesystem::path("C:\\Windows\\System32\\cmd.exe"), ::boost::process::windows::hide, env); // fine too

条件隐藏窗口并不是那么简单,因为windows::hidewindows::show是不同类型的,不能在同一个函数参数中传递。在这种情况下,需要编写自定义的安装程序处理程序:

struct show_window
:   ::boost::process::detail::handler_base
{
    private: ::boost::detail::winapi::WORD_ const m_flag;

    public: explicit
    show_window(bool const show) noexcept
    :   m_flag{show ? ::boost::detail::winapi::SW_SHOWNORMAL_ : ::boost::detail::winapi::SW_HIDE_}
    {}

    // this function will be invoked at child process constructor before spawning process
    template <class WindowsExecutor>
    void on_setup(WindowsExecutor &e) const
    {
        // we have a chance to adjust startup info
        e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESHOWWINDOW_;
        e.startup_info.wShowWindow |= m_flag;
    }
};

auto const need_to_show{false};
auto env{::boost::this_process::environment()};
::boost::process::child ch("cmd", env, show_window{need_to_show});

1
这比旧库好得多! - Aart Stuurman
1
请注意,原则上可以预期设置/错误/成功处理程序按(相反的)顺序调用。也就是说,除非库或扩展针对某些关键内部逻辑明确覆盖该逻辑。 - sehe
@VTT:如果一个人得到一个布尔值(bShowWindow)来有条件地设置SW_HIDESW_SHOW,该怎么处理呢?我尝试了(bShowWindow) ? ::boost::process::windows::show : ::boost::process::windows::hide,但它在child构造参数中无法编译... - jpo38
@VTT:太好了,谢谢!顺便问一下,如果您知道如何以同样的方式有条件地设置其他参数,例如流重定向,您可以尝试回答这个问题:https://stackoverflow.com/q/47630796/3336423 - jpo38

4

user7860670的回答是正确的,但我更喜欢create_no_window。

::boost::process::child ch1("myApp.exe", ::boost::process::windows::create_no_window); 

如果你在整个过程中都不需要窗口,那么你根本不需要创建它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接