CreateProcess 调用 cmd.exe 包括。没有显示(闪烁)窗口的参数?
Posted
技术标签:
【中文标题】CreateProcess 调用 cmd.exe 包括。没有显示(闪烁)窗口的参数?【英文标题】:CreateProcess calling cmd.exe incl. arguments with no showing (flashing) window? 【发布时间】:2017-10-04 19:23:24 【问题描述】:传奇还在继续……
我在网上搜索过,在 *** 上搜索过,我发现很多希望给出答案/解决方案,但不知何故,他们都失败了(包括与 ShellExecute(Ex) 相关的那些)。
如何使用 CreateProcess 隐藏(闪烁的)CMD 窗口(包括参数)?
我基本上想调用/执行一组条件/原生cmd.exe
命令(即FOR /F
和||
),还想调用/执行一个外部命令FIND(STR).exe
。而且,没有显示(闪烁的)CMD 窗口。
但即使隐藏像"cmd.exe /C ECHO ...flashing window is bad..."
这样简单的东西似乎也是不可能的。
我尝试过的代码(包括与dwFlags
和wShowWindow
标志相关的许多变体
#include <windows.h>
int main()
char cmdline[] = "cmd.exe /c ECHO ...flashing window is bad...";
PROCESS_INFORMATION pi;
STARTUPINFO si;
// memset(&si,0,sizeof(STARTUPINFO));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
// si.dwFlags = STARTF_USESTDHANDLES;
// si.dwFlags = CREATE_NO_WINDOW;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
// si.wShowWindow = CREATE_NO_WINDOW;
CreateProcess(NULL, (LPSTR) cmdline, NULL, NULL, 0, 0, NULL, NULL, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// ExitProcess;
return 0;
我不想依赖外部程序,即 .vbs(Windows 脚本宿主)或快捷方式,而只是一个独立编译的 .exe。
这是(真的)要求太多,还是我做错了(完全)?
谢谢...
【问题讨论】:
停止标签垃圾邮件。在随机添加看起来熟悉的标签之前,请阅读标签的描述。您添加的其中两个与您的问题无关。标签在这里有一个特定的定义和用途。main
入口点默认创建控制台应用程序。您是否覆盖了链接器的默认值?
Ken White:也许这些标签太笼统了。感谢您的建议。 - eryksun:你为什么要让我感到羞耻? ;-) 我查看了链接器的设置/选项,发现 不创建控制台窗口 (-mwindows) 设置为 no(即禁用)。启用它后,窗口不再出现/显示 o_O 附注:我以前玩过有问题的链接器设置,但当时它并没有以某种方式工作......称其为谜,但我仍然想知道为什么它现在突然起作用了。如果我将您的回答视为解决方法而不是解决方案,您介意吗?
【参考方案1】:
更新:您似乎也将CreateProcess
标志(它的dwCreationFlags
参数)与STARTUPINFO
结构的成员混淆了。这些是不同的标志,CREATE_NO_WINDOW
不应该在STARTUPINFO
中。
您必须传递CREATE_NO_WINDOW
标志,然后控制台窗口将不会显示。最初我回答说您必须重定向不正确的标准句柄(但仍然强烈推荐)。
设置STARTF_USESTDHANDLES
并填写适当的句柄。如果您对进程的输出感兴趣,请创建管道,否则您只需打开nul
传递即可。
【讨论】:
重定向标准句柄与显示控制台窗口是分开的。在内部实际上有 4 个标准 I/O 句柄——ConsoleHandle
、StandardInput
、StandardOutput
和 StandardError
。控制台输入/屏幕缓冲区句柄在没有附加到控制台的情况下是无用的,即内部ConsoleHandle
。控制台句柄也隐式用于不使用控制台缓冲区句柄的控制台函数,例如GetConsoleCP
。 AllocConsole
和 AttachConsole
函数可能设置所有 4 个句柄。
如果 CreateProcess
调用未指定 DETACHED_PROCESS
创建标志,则控制台应用程序会自动附加到其父控制台,或者当父控制台没有一或指定创建标志CREATE_NEW_CONSOLE
。如果后者都没有使用,那么CREATE_NO_WINDOW
可以用来创建一个没有窗口的新控制台。如果创建了带有窗口的新控制台,则可以通过启动信息中的SW_HIDE
隐藏该窗口。
感谢您指出错误(我是这方面的新手,我想我不必为此坦白;-))。关于标准输入/标准输出重定向:我假设您指的是 C++ 重定向方式而不是 CMD 重定向方式?我不知道 C++ 重定向到 null 的方式(我只见过将输出重定向到文件的示例)。很多这对我来说仍然是个谜,但我正在通过失败学习它,查看人们的代码,并且不害怕提出问题......我会看看我能做什么,但听起来还是有点对我来说是抽象的;-)
是的,我的意思是 C++ 重定向。 nul
是 Windows 提供的特殊文件/设备。
我在想什么 ;-) .. 也许我错了,但如果 IDE 提供了在执行时隐藏(不显示)控制台窗口的选项,编译器是否使用隐藏窗口(内部)的类似/可比方法/方式,就像使用 ShellExecute(Ex) 和 CreateProcess 的隐藏功能一样? (尽管后者让位于更多的控件/句柄)【参考方案2】:
尝试使用 ProcessBuilder。这是我拥有的一些代码的示例,它似乎工作得很好。在我下面的代码中,shellScript 是我动态创建的 StringBuilder,其中包含我要执行的命令及其参数。
String[] scriptArray = shellScript.toString().split(" ");
ProcessBuilder builder = new ProcessBuilder(scriptArray);
File outputFile = new File("/logs/AgentOutputLog.txt");
File errorFile = new File("/logs/AgentErrorLog.txt");
builder.redirectOutput(outputFile);
builder.redirectError(errorFile);
Process process = builder.start();
int errCode = process.waitFor();
//errCode = 0 means online
if(errCode == 0)
success = true;
break;
//errCode = 1 means offline
else if (errCode == 1)
success = false;
break;
【讨论】:
感谢您的提示/建议。我必须承认我对这个(C++)很陌生(bie),所以我很可能无法将所有拼图拼凑在一起。但我真的很感谢你提供的帮助!如果我能设法解决这个问题,我会让你知道我的发现。只是实现某事的方法/方法太多,这会使事情变得有点复杂/复杂(每种方法都有其优点/缺点)。我肯定会考虑你提供的代码 sn-p,但你必须明白,总会有更好的东西(更简单/简约)在拐角处;-)以上是关于CreateProcess 调用 cmd.exe 包括。没有显示(闪烁)窗口的参数?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 CreateProcess 中的 cmd.exe 的行为与 DOS 提示符不同?