spdcbr
spdcbr

Reputation: 365

How to execute a command in cmd using CreateProcess?

I'm trying to launch the command line through my c++ program and then have cmd run a command. I'm not sure what I'm doing wrong. I've looked at the MSDN documentation but I'm unable to understand what to change in my code.

Below is the chunk of code that I have written. I'm trying to launch cmd and then run the command in cmdArgs. However, on running the program it just launches the cmd without running the nslookup part of it. I've tried with other commands as well like ipconfig, but they do not get executed. Could someone help me understand what I'm doing wrong.

When I launch the program, it just opens up cmd. What I'm trying to do is have the cmdArgs runs and view the output on the cmd screen.

I'm new to c++, so if this is trivial I apologize. I've looked at other questions on the site, but it seems that the format of cmdArgs is correct - program name followed by the 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";
}

Upvotes: 2

Views: 28020

Answers (2)

Michael Haephrati
Michael Haephrati

Reputation: 4245

Try using this:

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);
}

Upvotes: 1

Serge Ballesta
Serge Ballesta

Reputation: 149175

Your program does exactly what you asked it to to: you just start the cmd.exe executable. Just test in a console windows:

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>

So cmd.exe ipconfig just pushed a new cmd.exe without executing the remaining of the line. It is then waiting for commands coming from its standard input.

You must use cmd.exe /c ipconfig to ask the new cmd.exe to execute a command, or cmd.exe /K ipconfig if you want cmd not to exit after first command:

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

Configuration IP de Windows
...

So you should write in your code:

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

Upvotes: 2

Related Questions