如何使用 CreateProcess 在 cmd 中执行命令?

Posted

技术标签:

【中文标题】如何使用 CreateProcess 在 cmd 中执行命令?【英文标题】:How to execute a command in cmd using CreateProcess? 【发布时间】:2016-09-26 12:20:27 【问题描述】:

我正在尝试通过我的 c++ 程序启动命令行,然后让 cmd 运行命令。我不确定我做错了什么。我查看了 MSDN 文档,但无法理解代码中要更改的内容。

以下是我编写的代码块。我正在尝试启动 cmd,然后在 cmdArgs 中运行该命令。但是,在运行程序时,它只是启动 cmd 而不运行它的 nslookup 部分。我尝试过使用其他命令以及 ipconfig,但它们没有被执行。有人可以帮我理解我做错了什么。

当我启动程序时,它只是打开了 cmd。我要做的是让 cmdArgs 运行并在 cmd 屏幕上查看输出。

我是 C++ 新手,所以如果这是微不足道的,我深表歉意。我查看了网站上的其他问题,但似乎 cmdArgs 的格式是正确的 - 程序名称后跟 arg。

STARTUPINFO si; 
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

LPTSTR cmdPath = _T("C:\\Windows\\System32\\cmd.exe");
LPTSTR cmdArgs = _T("C:\\Windows\\System32\\cmd.exe nslookup myip.opendns.com. resolver1.opendns.com");


if (!CreateProcess(cmdPath, cmdArgs, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))

    std::cout << "Create Process failed: " << GetLastError() << std::endl;
    return "Failed";

【问题讨论】:

您需要为命令行传递一个可写字符串,因为 CreateProcess 可能会按照文档中的说明对其进行修改。像TCHAR cmdArgs[] = _T("..."); 这样的东西如果你遇到了崩溃,你应该在调试器中运行它来找出哪里以及为什么。 你为什么要这样做?为什么不直接运行 nslookup? 【参考方案1】:

您的程序完全按照您的要求执行:您只需启动 cmd.exe 可执行文件。只需在控制台窗口中测试:

C:\Users\xxx>start /w cmd ipconfig

C:\Users\xxx>cmd ipconfig
Microsoft Windows [version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. Tous droits réservés.

C:\Users\xxx>exit

C:\Users\xxx>

所以cmd.exe ipconfig 只是推送了一个新的cmd.exe 而不执行剩余的行。然后它等待来自其标准输入的命令。

您必须使用cmd.exe /c ipconfig 要求新的cmd.exe 执行命令,如果您希望cmd 在第一个命令后不退出,则必须使用cmd.exe /K ipconfig

C:\Users\serge.ballesta>cmd /c ipconfig

Configuration IP de Windows
...

所以你应该写在你的代码中:

...
LPTSTR cmdArgs = _T("C:\\Windows\\System32\\cmd.exe /k nslookup myip.opendns.com. resolver1.opendns.com");
...

【讨论】:

“所以你应该在你的代码中写:LPTSTR cmdArgs = _T("string literal"); - 如果你希望CreateProcess 因访问冲突而失败。如果不这样做,请确保获取可修改的副本:TCHAR cmdArgs[] = _T("string literal");,并将地址传递给该副本的第一个元素。【参考方案2】:

试试这个:

wchar_t command[] = L"nslookup myip.opendns.com. resolver1.opendns.com";

wchar_t cmd[MAX_PATH] ;
wchar_t cmdline[ MAX_PATH + 50 ];
swprintf_s( cmdline, L"%s /c %s", cmd, command );

STARTUPINFOW startInf;
memset( &startInf, 0, sizeof startInf );
startInf.cb = sizeof(startInf);

PROCESS_INFORMATION procInf;
memset( &procInf, 0, sizeof procInf );

BOOL b = CreateProcessW( NULL, cmdline, NULL, NULL, FALSE,
    NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &startInf, &procInf );

DWORD dwErr = 0;
if( b ) 

    // Wait till process completes
    WaitForSingleObject( procInf.hProcess, INFINITE );
    // Check process’s exit code
    GetExitCodeProcess( procInf.hProcess, &dwErr );
    // Avoid memory leak by closing process handle
    CloseHandle( procInf.hProcess );
 
else 

    dwErr = GetLastError();

if( dwErr ) 

    wprintf(_T(“Command failed. Error %d\n”),dwErr);

【讨论】:

Haeharti 在底部你使用 procInfo 而不是 procInf。我尝试了这段代码,得到了 dwErr=2。 我修好了。谢谢

以上是关于如何使用 CreateProcess 在 cmd 中执行命令?的主要内容,如果未能解决你的问题,请参考以下文章

cmd.exe 在使用 CreateProcess 调用后立即关闭

尝试使用 createprocess (API) 在 cmd throw c++ 上运行命令?

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

Win32 API 类似于 CreateProcess,但适用于 bat/cmd/等。 (即使用 PATHEXT)

为啥 CreateProcess 中的 cmd.exe 的行为与 DOS 提示符不同?

将项目转换为支持 Unicode 后,CreateProcess 不运行 .cmd 文件