C++执行CMD命令

JP2*_*P29 14 c++ windows winapi cmd windows-console

我在这里遇到了严重的问题.我需要通过C++执行CMD命令行,而不显示控制台窗口.因此我无法使用system(cmd),因为窗口会显示.

我试过了winExec(cmd, SW_HIDE),但这也行不通.CreateProcess是我试过的另一个.但是,这适用于运行程序或批处理文件.

我最终尝试了ShellExecute:

ShellExecute( NULL, "open",
    "cmd.exe",
    "ipconfig > myfile.txt",
    "c:\projects\b",
    SW_SHOWNORMAL
);
Run Code Online (Sandbox Code Playgroud)

任何人都可以看到上述代码有什么问题吗?我已经习惯了,SW_SHOWNORMAL直到我知道这是有效的.

我真的需要一些帮助.没有任何事情发生,我已经尝试了很长一段时间.任何人都可以给出的建议会很棒:)

arx*_*arx 10

将输出重定向到您自己的管道是一个更整洁的解决方案,因为它避免了创建输出文件,但这工作正常:

ShellExecute(0, "open", "cmd.exe", "/C ipconfig > out.txt", 0, SW_HIDE);
Run Code Online (Sandbox Code Playgroud)

您没有看到cmd窗口,并且输出按预期重定向.

您的代码可能会失败(除了/C东西),因为您指定路径"c:\projects\b"而不是"c:\\projects\\b".


Céd*_*oys 6

这是我对DosExec函数的实现,该函数允许(静默)执行任何DOS命令并以unicode字符串的形式检索生成的输出。

// Convert an OEM string (8-bit) to a UTF-16 string (16-bit) 
#define OEMtoUNICODE(str)   CHARtoWCHAR(str, CP_OEMCP)

/* Convert a single/multi-byte string to a UTF-16 string (16-bit).
 We take advantage of the MultiByteToWideChar function that allows to specify the charset of the input string.
*/
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) {
    size_t len = strlen(str) + 1;
    int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0);
    LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed);
    MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed);
    return wstr;
}

/* Execute a DOS command.

 If the function succeeds, the return value is a non-NULL pointer to the output of the invoked command. 
 Command will produce a 8-bit characters stream using OEM code-page.

 As charset depends on OS config (ex: CP437 [OEM-US/latin-US], CP850 [OEM 850/latin-1]),
 before being returned, output is converted to a wide-char string with function OEMtoUNICODE.

 Resulting buffer is allocated with LocalAlloc.
 It is the caller's responsibility to free the memory used by the argument list when it is no longer needed. 
 To free the memory, use a single call to LocalFree function.
*/
LPWSTR DosExec(LPWSTR command){
    // Allocate 1Mo to store the output (final buffer will be sized to actual output)
    // If output exceeds that size, it will be truncated
    const SIZE_T RESULT_SIZE = sizeof(char)*1024*1024;
    char* output = (char*) LocalAlloc(LPTR, RESULT_SIZE);

    HANDLE readPipe, writePipe;
    SECURITY_ATTRIBUTES security;
    STARTUPINFOA        start;
    PROCESS_INFORMATION processInfo;

    security.nLength = sizeof(SECURITY_ATTRIBUTES);
    security.bInheritHandle = true;
    security.lpSecurityDescriptor = NULL;

    if ( CreatePipe(
                    &readPipe,  // address of variable for read handle
                    &writePipe, // address of variable for write handle
                    &security,  // pointer to security attributes
                    0           // number of bytes reserved for pipe
                    ) ){


        GetStartupInfoA(&start);
        start.hStdOutput  = writePipe;
        start.hStdError   = writePipe;
        start.hStdInput   = readPipe;
        start.dwFlags     = STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
        start.wShowWindow = SW_HIDE;

// We have to start the DOS app the same way cmd.exe does (using the current Win32 ANSI code-page).
// So, we use the "ANSI" version of createProcess, to be able to pass a LPSTR (single/multi-byte character string) 
// instead of a LPWSTR (wide-character string) and we use the UNICODEtoANSI function to convert the given command 
        if (CreateProcessA(NULL,                    // pointer to name of executable module
                           UNICODEtoANSI(command),  // pointer to command line string
                           &security,               // pointer to process security attributes
                           &security,               // pointer to thread security attributes
                           TRUE,                    // handle inheritance flag
                           NORMAL_PRIORITY_CLASS,   // creation flags
                           NULL,                    // pointer to new environment block
                           NULL,                    // pointer to current directory name
                           &start,                  // pointer to STARTUPINFO
                           &processInfo             // pointer to PROCESS_INFORMATION
                         )){

            // wait for the child process to start
            for(UINT state = WAIT_TIMEOUT; state == WAIT_TIMEOUT; state = WaitForSingleObject(processInfo.hProcess, 100) );

            DWORD bytesRead = 0, count = 0;
            const int BUFF_SIZE = 1024;
            char* buffer = (char*) malloc(sizeof(char)*BUFF_SIZE+1);
            strcpy(output, "");
            do {                
                DWORD dwAvail = 0;
                if (!PeekNamedPipe(readPipe, NULL, 0, NULL, &dwAvail, NULL)) {
                    // error, the child process might have ended
                    break;
                }
                if (!dwAvail) {
                    // no data available in the pipe
                    break;
                }
                ReadFile(readPipe, buffer, BUFF_SIZE, &bytesRead, NULL);
                buffer[bytesRead] = '\0';
                if((count+bytesRead) > RESULT_SIZE) break;
                strcat(output, buffer);
                count += bytesRead;
            } while (bytesRead >= BUFF_SIZE);
            free(buffer);
        }

    }

    CloseHandle(processInfo.hThread);
    CloseHandle(processInfo.hProcess);
    CloseHandle(writePipe);
    CloseHandle(readPipe);

    // convert result buffer to a wide-character string
    LPWSTR result = OEMtoUNICODE(output);
    LocalFree(output);
    return result;
}
Run Code Online (Sandbox Code Playgroud)


Fel*_*ano 5

您应该在参数上使用CreateProcess来隧道化ipconfig命令。>本身在命令行上不起作用。您必须以编程方式重定向stdoutcmd.exe/C

  • 如果它是一个`cmd /c` 命令行,那么`>` 重定向当然可以工作。 (2认同)