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..." 这样简单的东西似乎也是不可能的。

我尝试过的代码(包括与dwFlagswShowWindow 标志相关的许多变体

#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 句柄——ConsoleHandleStandardInputStandardOutputStandardError。控制台输入/屏幕缓冲区句柄在没有附加到控制台的情况下是无用的,即内部ConsoleHandle。控制台句柄也隐式用于不使用控制台缓冲区句柄的控制台函数,例如GetConsoleCPAllocConsoleAttachConsole 函数可能设置所有 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 提示符不同?

CreateProcess() API 函数有啥用?

CreateProcess cmd.exe 读/写管道死锁

如何使用 CreateProcess 函数正确调用“telnet”?

被粘滞键调用时 CreateProcess 访问被拒绝

VC++ std::system() API 在调用 CMD.exe 后立即返回