CreateProcess 不会在 Windows 7 下创建额外的控制台窗口? [英] CreateProcess does not create additional console windows under Windows 7?

查看:55
本文介绍了CreateProcess 不会在 Windows 7 下创建额外的控制台窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 CreateProcess(...) 运行一个进程,并在单独的控制台窗口中独立运行它.

我可以使用 system("...") 函数来实现这一点,但我更喜欢 CreateProcess,因为它让我可以指定环境和工作目录,获取进程的句柄,以及管道 stdin/out当我需要的时候.

我在互联网上发现的只是相反的问题,即人们拥有额外的控制台窗口并希望摆脱它们!在早期版本的 Windows 中,打开并显示新的控制台窗口似乎是正常行为?

现在,即使我运行cmd.exe/c ...",我也无法获得额外的窗口

我尝试使用 STARTF_USESHOWWINDOW 标志但没有成功.

有人遇到过这个问题吗?

PS.:显示 GUI 窗口,例如.notepad.exe 会正常出现.

这是我的代码(本质上)

PROCESS_INFORMATION processInfo;STARTUPINFOA 启动信息;ZeroMemory(&startupInfo,sizeof(startupInfo));startupInfo.dwFlags |= CREATE_NEW_CONSOLE;startupInfo.dwFlags |= DETACHED_PROCESS;ok&=CreateProcessA( NULL,const_cast<char*>(comand.c_str()),//对于 CreateProcessA 是安全的空,空,真,空,空,空,&startupInfo, &processInfo);

我正在尝试运行 C:/Windows/system32/cmd.exe/c help程序运行,我可以从管道读取输出.仍然没有窗口.

解决方案

MSDN 确实是您使用 Win32 API 时最好的朋友.现在,您的相关创建标志如下:

(no flags set) — 子进程(使用 CreateProcess() 启动的进程)将与父进程(调用 CreateProcess() 的进程)共享控制台代码>CreateProcess()).

CREATE_NEW_CONSOLE — 子进程将收到一个新的控制台,在新窗口中打开.正如 MSDN 明确指出的那样,此标志不得与 DETACHED_PROCESS 一起使用,而这正是您要使用的标志.>

CREATE_NO_WINDOW — 子进程将收到一个新的控制台,但没有任何窗口.这是一个非常令人惊讶的标志,所以我将再次重申:子进程将有一个控制台,您可以将输出写入其中,您可以尝试从中读取输入等;这个控制台不同于父进程的控制台;这个控制台是不可见的,它没有可见的窗口,但它存在.例如,它对于在后台静默运行子进程很有用.请注意,当与 CREATE_NEW_CONSOLEDETACHED_PROCESS 一起使用时,此标志无效 - 这些标志会覆盖此标志.另请记住,启动 GUI 应用程序时会忽略此标志:它不会收到不可见的控制台.

DETACHED_PROCESS — 子进程不会收到任何控制台.您不得将此标志与 CREATE_NEW_CONSOLE 一起使用.

现在更多地了解 CreateProcess() 的正确调用.首先,您应该使用 CreateProcessW().我特别厌倦了无法访问名为 日本​​语αβηλ 目录中文件的应用程序.

其次,即使您使用 ANSI 版本,如果您为环境传递 NULL,请指定 CREATE_UNICODE_ENVIRONMENT 标志.如果你不这样做,PATH 可能最终会在子进程中被破坏,这个错误非常烦人.

第三,不要const_castcommand.c_str().只需在其上调用 strdup()/wcsdup(),然后在 CreateProcess() 调用返回后调用 free().或者,如果你真的坚持修改 command 就地,传递 &command[0] 作为参数.

第四,不要忘记设置你的STARTUPINFO结构的大小:startupInfo.cb = sizeof(startupInfo).现代 Windows(至少是 XP 和 7)实际上允许您将此字段保留为零而不会产生任何有害后果,但依赖于此有点草率编程.

哦,虽然我们在这里:您提到您使用 CreateProcess() 是因为,除其他外,它允许您为子项明确指定环境.嗯,有一个关于 lpEnvironment 参数的小问题,它被记录在案,但很容易被忽视.当您指定 NULL 时,子级将继承父级的环境.当您指定非NULL 的内容时,不会向其中添加父级环境.如果你想添加到父级的环境中,你必须使用 GetEnvironmentStrings() 来获取它,然后显式地调整它.

I am trying to run a process using CreateProcess(...) and run it independently in a seperate console window.

I can achieve this using the system("...") function, but I prefer CreateProcess since it gives me the possibility to specify environment and working directory, get a handle to the process, as well as piping stdin/out when I need to.

All I find on the internet is the inverse problem, which is people having additional console windows and wanting to get rid of them! It appears it was the normal behavior in earlier versions of Windows to open and show a new console window(s)?

Right now, I am unable to get an additional window, even if I run "cmd.exe /c ..."

I tried using the STARTF_USESHOWWINDOW flag with no luck.

Has anyone had this problem?

PS.: GUI windows are shown eg. notepad.exe will appear normally.

This is my code (in essence)

PROCESS_INFORMATION processInfo;
STARTUPINFOA startupInfo;
ZeroMemory(&startupInfo,sizeof(startupInfo));
startupInfo.dwFlags |= CREATE_NEW_CONSOLE;
startupInfo.dwFlags |= DETACHED_PROCESS;
ok&=CreateProcessA( NULL,
    const_cast<char*>(comand.c_str()), // safe for CreateProcessA
    NULL, NULL, TRUE, NULL, NULL, NULL,
    &startupInfo, &processInfo);

I'm trying to run C:/Windows/system32/cmd.exe /c help The program runs and I can read the output from a pipe. Still no window.

解决方案

MSDN is really your best friend while working with Win32 API. Now, the relevant creation flags for you are the following:

(no flags set) — the child process (the one being started with CreateProcess()) will share the console with the parent process (the process which called CreateProcess()).

CREATE_NEW_CONSOLE — the child process will receive a new console, open in a new window. As the MSDN explicitly says, this flag MUST NOT be used together with DETACHED_PROCESS! And that's exactly the flag that you want to use.

CREATE_NO_WINDOW — the child process will receive a new console, but without any window for it. That's quite a surprising flag, so I will restate it again: the child process will have a console, to which you can write your output, from which you can try to read input, etc; this console is different from the parent process's console; this console is invisible, it has no visible window, but it exists. It's useful for, say, silently running child processes in background. Note that this flag has no effect when used with CREATE_NEW_CONSOLE or DETACHED_PROCESS — those flags override this one. Also keep in mind that this flag is ignored when you launch a GUI application: it won't receive an invisible console.

DETACHED_PROCESS — the child process will not receive any console whatsoever. You must not use this flag together with CREATE_NEW_CONSOLE.

And now a bit more about correct invocation of CreateProcess(). First of all, you should use CreateProcessW(). I am particularly tired of apps that can't access files in a directory named 日本語αβηλ.

Second, even if you use the ANSI version, specify CREATE_UNICODE_ENVIRONMENT flag if you pass NULL for the environment. If you don't do this, PATH may end up broken in the child process, and this bug is extremely annoying to trace down.

Third, don't const_cast<char*>command.c_str(). Just call strdup()/wcsdup() on it, and then free() after the CreateProcess() call returned. Or if you really insists on modifying command in place, pass &command[0] as the parameter.

Fourth, don't forget to set the size of your STARTUPINFO structure: startupInfo.cb = sizeof(startupInfo). Modern Windows (XP and 7, at least) actually allow you to leave this field to be a zero without any harmful consequences, but it's a bit of a sloppy programming to rely on this.

Oh, and while we are here: you mentioned that you use CreateProcess() because, among other things, it allows you to specify environment for the child explicitly. Well, there is a slight gotcha about lpEnvironment parameter which is documented, but quite easily overlooked. When you specify NULL, the child inherits the parent's environment. When you specify something non-NULL, the parent's environment IS NOT ADDED to it. If you want to add to the parent's environment, you'd have to use GetEnvironmentStrings() to obtain it and then explicitly tweak it.

这篇关于CreateProcess 不会在 Windows 7 下创建额外的控制台窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆