【问题标题】:Hiding command prompt called by system();隐藏由 system() 调用的命令提示符;
【发布时间】:2012-09-23 16:54:38
【问题描述】:

Goodday,我有脚本,它循环目录中的所有文件,但我需要隐藏控制台,同时以这种方式循环它们。 这是脚本的一部分:

#include <iostream>
#include <fstream>
#include <Windows.h>
using namespace std;

 int GetFilesInDirectory(const char * dir,string dest[],unsigned int max){
    string loc=dir;
    int ctr=0;
    if(loc.length()>2)
        if(loc.substr(loc.length()-2,1)=="\\")
            loc=loc.substr(0,loc.length()-1);
    string opcommand;
    string delcommand;
    if(loc.length()>2){
        opcommand="cd "+(loc)+" && dir /s /b /a > tmpfile.cpptmp";
        delcommand="cd "+(loc)+" && del tmpfile.cpptmp";
    } else {
        opcommand="dir /s /b /a > tmpfile.cpptmp";
        delcommand="del tmpfile.cpptmp";
    }
    system(opcommand.c_str());
    ifstream f;
    string line;
    string fileloc;
    if(loc.length()>2)
        fileloc=(loc)+"\\tmpfile.cpptmp";
    else fileloc="tmpfile.cpptmp";
    f.open(fileloc,ios::binary);
    while(f.good()){
        getline(f,line);
        if(line.length()>1&&ctr<max){
            dest[ctr]=line;
            ctr++;
        }
    }
    f.close();
    system(delcommand.c_str());
    return ctr;
}
int main() {
    FreeConsole();
    const unsigned int filescountmax=16184;

    string files[filescountmax];
    int count=GetFilesInDirectory("\\",files,filescountmax);
    string ext;
    for(int i=0;i<count;i++){
            //some script

    }
}

当进程启动时,它会自行隐藏它,但之后它会显示 cmd.exe,它会自行关闭它。 顺便说一句,我知道还有其他方法可以循环目录中的文件,但这是循环子目录和子目录的子目录等中的文件的最简单方法。 你能帮帮我吗?

【问题讨论】:

  • 我认为CreateProcess 可用于在不显示命令提示符的情况下拨打system
  • @WaleedKhan,我很确定你可以将第四个参数指定给WinMain,所以只要进程使用它来确定状态,那就对了。
  • 如果要列出和删除目录中的文件,为什么不使用为此提供的 Windows API 函数呢?例如,有一个tutorial on listing directory contents。执行 cmd.exe 来做这些事情有点傻——就像你用 C++ 编写了一个批处理文件。
  • 或者您可以使用 boost 并让解决方案跨平台。你甚至可以试试 TR2 的 &lt;filesystem&gt; 标头。
  • 我不知道如何使用 CreateProcess :(

标签: c++ windows


【解决方案1】:

您可以更改子系统以使 Windows 隐藏控制台。在你的源代码中添加这个命令:

#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )

或者,您可以尝试带有标志CREATE_NO_WINDOWCreateProcess 函数。

【讨论】:

  • 我正在尝试这个: CreateProcess(L"C:\\Windows\\System32\\cmd.exe",LPWSTR(cmd),0,0,false,CREATE_NO_WINDOW,NULL,NULL,&si ,&pi),但它不起作用:( char * cmd="echo hello >textfile.txt";
  • @DieMeine:CreateProcess 的第二个参数需要是 wchar_t 缓冲区(它必须是可写内存)。或者,使用 CreateProcessA;你可以用 const char * 来调用它。
  • 你可以试试这个:_TCHAR *cmd = L"echo hello >textfile.txt"
  • @user1692432:这样不行,CreateProcessW的第二个参数不能是常量字符串,加上要执行的shell命令需要以/c为前缀。像这样: wchar_t cmd[] = L"cmd /c echo hello > testfile.txt"
  • @DieMeine:检查CreateProcess的返回码,如果为零则调用GetLastError获取错误码。
【解决方案2】:

这是我为此类任务编写的系统函数的模拟。

int system_hidden(const char *cmdArgs)
{
    PROCESS_INFORMATION pinfo;
    STARTUPINFO sinfo;

    /*
     * Allocate and hide console window
     */
    AllocConsole ();
    ShowWindow (GetConsoleWindow(), 0);

    memset (&sinfo, 0, sizeof (sinfo));
    sinfo.cb = sizeof (sinfo);
    CreateProcess (NULL, (char*)cmdArgs,
                   NULL, NULL, false,
                   0,
                   NULL, NULL, &sinfo, &pinfo);
    DWORD ret;
    while (1)
    {
        HANDLE array[1];
        array[0] = pinfo.hProcess;
        ret = MsgWaitForMultipleObjects (1, array, false, INFINITE,
                                         QS_ALLPOSTMESSAGE);
        if ((ret == WAIT_FAILED) || (ret == WAIT_OBJECT_0))
            break;
        /*
         * Don't block message loop
         */
        MSG msg;
        while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
    }

    DWORD pret;
    GetExitCodeProcess (pinfo.hProcess, &pret);
//    FreeConsole ();
    return pret;
}

【讨论】:

  • 与其显式分配然后隐藏控制台窗口,不如在 CreateProcess 调用中使用 CREATE_NO_WINDOW 标志。
  • 无论如何,它什么也没做 :( 我试过 system_hidden("echo hi>text.txt"); 什么也没发生,应用程序崩溃了
  • @DieMeine:两个问题;首先,该代码不会在 Unicode 应用程序中按原样编译,您需要将 CreateProcess 更改为 CreateProcessA。其次,CreateProcess 不使用 shell,因此 echo 和输出重定向等内部命令无效。您需要显式调用 shell:system_hidden("cmd /c echo hi > test.txt")
  • @Harry Johnston,感谢您发现代码中的不准确之处。我手头没有 Visual Studio。
  • 还要感谢 Harry Johnston,它帮助很大,但公平地说,我使用了 alexander 的代码,所以这是一个答案 :)
【解决方案3】:

我注意到接受的答案有点过于复杂。这是在没有新的cmd.exe 窗口的情况下执行命令的更简单方法。基于this answer by Roland Rabien'sMSDN

int windows_system(const char *cmd)
{
  PROCESS_INFORMATION p_info;
  STARTUPINFO s_info;
  LPSTR cmdline, programpath;

  memset(&s_info, 0, sizeof(s_info));
  memset(&p_info, 0, sizeof(p_info));
  s_info.cb = sizeof(s_info);

  cmdline     = _tcsdup(TEXT(cmd));
  programpath = _tcsdup(TEXT(cmd));

  if (CreateProcess(programpath, cmdline, NULL, NULL, 0, 0, NULL, NULL, &s_info, &p_info))
  {
    WaitForSingleObject(p_info.hProcess, INFINITE);
    CloseHandle(p_info.hProcess);
    CloseHandle(p_info.hThread);
  }
}

适用于所有 Windows 平台。像您一样拨打电话system()

【讨论】:

  • 如果命令有任何参数,或者是内置命令而不是可执行文件,则不会按预期工作。它也不会抑制命令行可执行文件的控制台窗口。
【解决方案4】:

我用这个,只支持run block cmd。比如在destktop中创建shortcat,比如打开notepad.exe编辑文件等等。

#define MAX_SYSTEM_PROGRAM (4096)
static int windows_system(const wchar_t *cmd)
{
    PROCESS_INFORMATION p_info;
    STARTUPINFO s_info;
    DWORD ReturnValue;

    memset(&s_info, 0, sizeof(s_info));
    memset(&p_info, 0, sizeof(p_info));
    s_info.cb = sizeof(s_info);

    wchar_t utf16cmd[MAX_SYSTEM_PROGRAM] = {0};
    MultiByteToWideChar(CP_UTF8, 0, cmd, -1, utf16cmd, MAX_SYSTEM_PROGRAM);
    if (CreateProcessW(NULL, utf16cmd, NULL, NULL, 0, 0, NULL, NULL, &s_info, &p_info))
    {
        WaitForSingleObject(p_info.hProcess, INFINITE);
        GetExitCodeProcess(p_info.hProcess, &ReturnValue);
        CloseHandle(p_info.hProcess);
        CloseHandle(p_info.hThread);
    }
    return ReturnValue;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    相关资源
    最近更新 更多