i hev problem with CreatProcess function introduced in windows.h header for c++.
whenever i try to pass it a TCHAR variable containing a cmd command it returns error : CreateProcess failed (2) .
and for this am waiting for your explanations and solutions.
consider code below:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( argc != 2 )
{
printf("Usage: %s [cmdline]\n", argv[0]);
return 0;
}
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
argv[1], // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return 0;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
notice:when i launch an application with specifying its path ..it works fine like=> "c:\code.exe";
If you want to run a command DOS, you have to run the shell cmd before.
CreateProcess doesn't do that for you.
The option /c of cmd permits to run a command in the shell and terminate. You just have to build a command line of the type cmd /c <your command here>.
I compiled your code on VS2012 and I tried : test.exe "cmd /c dir" and it works like a charm.
From the Microsoft documentation :
To run a batch file (or a batch command), you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file.
Source : http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
In order to execute a command implemented by the command shell aka cmd.exe, you need to actually run cmd.exe. CreateProcess doesn't automatically do that for you.
Build a command line of the form cmd.exe /c <your command here>. /c means "run one command, then terminate".
Related
I was just playing with Win32-API and wanted to create a process using CreateProcess function. I used the following code from MSDN website:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( argc != 2 )
{
printf("Usage: %s [cmdline]\n", argv[0]);
return;
}
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
argv[1], // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
But surprisingly I can't create a dir process using this piece of code. Error code indicated that 'The system cannot find the file specified.'
I'm using Visual studio 2015 and Windows 7 64Bit. But when I run the same executable in Windows 10, everything is OK.
dir is not an external command that can be run. It's a command internal to the Windows Command Prompt. You'll need to call your program as myprogram "cmd /c dir" to do that.
Of course, there are better ways to iterate a directory than calling an external program, but that's a separate question.
After hours of going through 1500 lines of C code, it finally dawned on me what my problem was and why it worked on one Windows 10 system of mine but not on another. The system that it worked on, I really did have a DIR.EXE. But is was not the COMSPEC DIR that was running. I had DIR.EXEs in Git and MinGW folders.
Read this for how to correctly use CREATEPROCESS.
https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa
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";
}
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");
...
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);
}
I am trying to create a process that send command to cmd.exe and receive Error 2,
Why? It's posible? How?
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
String pathexe = "C:\Windows\system32\cmd.exe";
String command= "notepad.exe";
if(!CreateProcess(
pathexe.c_str(), // lpApplicationName
command.c_str(), // lpCommandLine
NULL, // lpProcessAttributes
NULL, // lpThreadAttributes
FALSE, // bInheritHandles
0, // dwCreationFlags
NULL, // lpEnvironment
NULL, // lpCurrentDirectory
&si, // lpStartupInfo
&pi // lpProcessInformation
))
{
AnsiString error = GetLastError();
ShowMessage("Error: " + error);
}
WaitForSingleObject( pi.hProcess, INFINITE );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
PD: 1) It is assumed that you can use CreateProcess () for this purpose, I should not do it with ShellExecute () or system().
2) I have read about it in the forum and can not find a solution to this error, there are many answers to similar questions but do not address the error, other functions are proposed, or mix with the route command.
3) I do not think that issue permits because I built while the manifest.
4) I currently use C ++ Builder, in win7, 32bits but not important.
5) I guess the issue will be voted as negative and duplicate (as usual) but the proposed testing examples also receive errors.
Thanks to all
FIRST CONCLUSIONS:
Error 2: The system cannot find the file specified.
Link funtion: https://msdn.microsoft.com/es-es/library/windows/desktop/ms679360(v=vs.85).aspx
Link error: https://msdn.microsoft.com/es-es/library/windows/desktop/ms681382(v=vs.85).aspx
With error 2: check syntax, file path and existence.
works:
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
String command = "notepad.exe";
if(!CreateProcess(
NULL, // lpApplicationName
commmand.c_str(), // lpCommandLine
NULL, // lpProcessAttributes
NULL, // lpThreadAttributes
FALSE, // bInheritHandles
0, // dwCreationFlags
NULL, // lpEnvironment
NULL, // lpCurrentDirectory
&si, // lpStartupInfo
&pi // lpProcessInformation
))
{
AnsiString error = GetLastError();
ShowMessage("Error: " + error);
}
WaitForSingleObject( pi.hProcess, INFINITE );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
This example works also for exe
String command = "cd C:\\sample\\calc.exe";
But no with cmd´s general commands, there must be a way to send commands to cmd as:
notepad.exe && cd C:\sample\ && sample1.txt
THANKS TO ALL
You're trying to run this command:
cmd notepad
(You aren't doing that quite right, either; the lpCommandLine argument should include the entire string, not just notepad, and you haven't quoted the backslashes properly.)
But even once you fix those problems, it won't work, because you've got the syntax wrong. You'll find it won't work if typed on the command line either!
Instead, try:
String pathexe = "C:\\Windows\\system32\\cmd.exe";
String command= "cmd /c notepad.exe";
The /c option means "run this command". You can use /k instead if you want the command window to stay open after the command has finished, though it's unusual for a program to do so.
One final note: I'm assuming here than notepad is just a stand-in for a more complicated command. If you actually want to run notepad, or any other executable, you shouldn't be invoking cmd.exe at all:
String command= "notepad";
if(!CreateProcess(
NULL, // lpApplicationName
command.c_str(), // lpCommandLine
...
You only need to call on cmd.exe if you need to run a built-in command, or a composite command line.
(Actually, calling cmd.exe is considered poor practice even in those cases; in Windows, you are generally expected do that sort of thing for yourself via the API rather than farming out the job to the command interpreter. But there are edge cases, and your mileage may vary.)
ello all I hope someone can help me with this issue I am using the following example from msdn for createprocess function.
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( argc != 2 )
{
printf("Usage: %s [cmdline]\n", argv[0]);
return;
}
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
argv[1], // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
This is accessed via dos and works perfectly using this command in command prompt. When I type this
this.exe "my.exe test" > result.txt
The my.exe is another console application that takes the input test and the > result.txt is for my output log. I am trying to remove the need for the command line so I am trying to feed the path into the createprocess function call. This is where I get stuck here is what I am trying
if( !CreateProcess( NULL, // No module name (use command line)
"\"my.exe test \" > result.txt", // this.exe "my.exe test" > result.txt
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
still doesnt work I thought \" would give me the result I needed but it doesnt seem to work, will parse the my.exe and test part but not the > result.txt output. However it works from the command prompt fine if i pass it to argv[1].
Any help much appreciated.
So in summary
In console I can parse
this.exe "my.exe test" > result.txt // Works fine via cmd.exe
To app I tried
my.exe test > result.txt // Not work but missing ""
and
\"my.exe test \" > result.txt // work for first section
CreateProcess only does basic command line parsing by breaking up the words into individual arguments -- it doesn't understand file redirection or anything. If you pass it "> result.txt", it tries to parse that as two arguments named literally ">" and "result.txt".
If you want to redirect the output of the command, you have two options:
Do the redirection yourself. To do that, you'd first open the file with CreateFile (passing in security attributes which make the handle inheritable), and then assign the resulting handle to the hStdOut member of the STARTUPINFO structure you pass in. Then, remember to close the file after CreateProcess returns, since otherwise you'd leak a handle.
Use another program to do the redirection. When you type in commands on the command line, it's cmd.exe which parses your command line and does the file redirection. So instead of creating a my.exe process, you could instead create a cmd.exe process with a command line something like this:
cmd.exe "my.exe test > result.txt"
CreateProcess only expects an executable name and some arguments. The redirection is actually not a program argument. That is interpreted by the shell (cmd.exe).
What is happening when you invoke your own program is as follows...
cmd> this.exe "my.exe test" > result.txt
argv[0] = "this.exe"
argv[1] = "my.exe test"
Output is sent to result.txt by the shell
Now, your one that doesn't work:
cmd> this.exe my.exe test > result.txt
argv[0] = "this.exe"
argv[1] = "my.exe"
argv[2] = "test"
Output is sent to result.txt by the shell
You'll see that because you only send argv[1] to CreateProcess, the behaviour is not as you expected.
Now, as I mentioned, CreateProcess does not actually redirect output. To do that, you should use the system call which invokes cmd.exe or whatever command interpreter the system uses:
system( "my.exe test > result.txt" );
See: http://msdn.microsoft.com/en-us/library/277bwbdz(v=vs.80).aspx
I am using this piece of code to launch a process from a GUI app. but, according to the notes of this code it is not possible to launch a process from a console app. actually i want to do that, I want a console app to launch another console process, please do you have any idea how to do that?
// This technique must be used for "console-less" parents such as GUI
// applications or detached applications.
// Using the STARTUPINFO STARTF_USESTDHANDLES flag, requires that
// the CreateProcess fInheritHandles parameter be set TRUE so that
// the file handles specified in the STARTUPINFO structure will be
// inherited by the child.
// setup the child process's handles for stdin, stdout, & stderr.
STARTUPINFO childProcStartupInfo;
memset( &childProcStartupInfo, 0, sizeof(childProcStartupInfo));
childProcStartupInfo.cb = sizeof(childProcStartupInfo);
childProcStartupInfo.hStdInput = hFromParent; // stdin
childProcStartupInfo.hStdOutput = hToParent; // stdout
childProcStartupInfo.hStdError = hToParentDup; // stderr
childProcStartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
childProcStartupInfo.wShowWindow = SW_HIDE;
// Now create the child process, inheriting handles
PROCESS_INFORMATION childProcInfo; /* for CreateProcess call */
bOk = CreateProcess(
NULL, // filename
pCmdLine, // full command line for child
NULL, // process security descriptor */
NULL, // thread security descriptor */
TRUE, // inherit handles? Also use if STARTF_USESTDHANDLES */
0, // creation flags */
NULL, // inherited environment address */
NULL, // startup dir; NULL = start in current */
&childProcStartupInfo, // pointer to startup info (input) */
&childProcInfo); // pointer to process info (output) */
did you try shellexecute? I think that works..
You can try:
ShellExecute(), ShellExecuteEx(), CreateProcess(), system(), _wsystem().
There are a few more, but one of these got to work for you!
Personally, I would go with CreateProcess and than wait for the process to quit (found on google this example: http://www.codeproject.com/Tips/333559/CreateProcess-and-wait-for-result). Notice that system()/_wsystem() are the easiest to use, but if you're not careful they can be exploited !!!
Hope it helps! :-)
Try this code:
#include <Windows.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
char* app_to_launch=new char[80];
strcpy(app_to_launch,"app.exe");
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
app_to_launch, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
return 0;
}