grep: input file ">":System cannot find the file specified - c++

when I tried to execute a grep command in c++, I got the following error:
grep: Input file: ">":System cannot find the file specified
Can anyone help me to resolve this?
wchar_t* grepArg= L"\"D:\\grep\" -f \"C:\\Users\\ic014733\\AppData\\Local\\Temp\\patterns.tmp\" \"D:\\LOG2014_10_05.LOG\" >\"D:\\share\\result.txt\"";
if ( !CreateProcessW(NULL, grepArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) )
{
DWORD errorMessageID = ::GetLastError();
}
else
{
DWORD res = WaitForSingleObject(pi.hProcess, INFINITE);
TerminateProcess(pi.hProcess, 0);
PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0) ;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}

You gave the answer in your comment : Error is like, grep considers '>' too as input file. Of course it does! Why should it not?
Let me explain a little: When you write grep -f strings_file file > result at a shell prompt (or cmd prompt under Windows), the shell parses the input line, indentifies the > redirection and processes the redirection:
open result file
start program grep with arguments (or command line for Windows) -f strings_file file and standard output redirected to result
But you are just starting the grep program with all the arguments in its command line, so no redirection can happen.
So what can you do? As none of your path contains spaces, you could just make cmd.exe do the redirection for you :
wchar_t* grepArg= L"cmd.exe /C \"D:\\grep -f C:\\Users\\ic014733\\AppData\\Local\\Temp\\patterns.tmp D:\\LOG2014_10_05.LOG > D:\\share\\result.txt";
That means that you start a new cmd.exe program with two parameters: /c saying execute that and your original command enclosed in quotes. But I never found the way to cleanly include quotes in quotes in Windows. That's the reason why I removed all the inner quotes from your command. It was possible because there was no space in any path.
The alternative would be to do the redirection by hand: open the output file, pass its handle in the hStdOutput member of si and declare it by setting STARTF_USESTDHANDLES in dwFlags member of same struct:
wchar_t* grepArg= L"\"D:\\grep\" -f \"C:\\Users\\ic014733\\AppData\\Local\\Temp\\patterns.tmp\" \"D:\\LOG2014_10_05.LOG\"";
HANDLE hstdout = CreateFile("D:\\share\\result.txt", "GENERIC_WRITE", 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// control hstdout is not null...
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdOutput = hstdout;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); // stdinput and stderr unchanged
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if ( !CreateProcessW(NULL, grepArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) ) {
...

Related

trying to delete a file in Temp dir using CreateProcessA

Hello I am trying to delete a file using following code:
CreateProcessA(NULL, (LPSTR)"del /f C:\\Users\\samee\\AppData\\Local\\Temp\\tempFile.txt", 0, 0, true, CREATE_NO_WINDOW, 0, 0, &si, &pi);
however this is not working. What am doing wrong here?
del is not an executable that you can run directly. It is a built-in command of the cmd.exe shell. So, you would need to run cmd.exe instead, using its /C or /K parameter to execute shell commands, eg:
char cmdLine[] = "cmd.exe /C del /f C:\\Users\\samee\\AppData\\Local\\Temp\\tempFile.txt";
CreateProcessA(NULL, cmdLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
But why do that? The Win32 API has a DeleteFileA() function, you should use that instead, eg:
DeleteFileA("C:\\Users\\samee\\AppData\\Local\\Temp\\tempFile.txt");
Note that the /f parameter of del allows for deleting a read-only file. If DeleteFileA() fails because the file is read-only, then simply remove the read-only flag, eg:
char fileName[] = "C:\\Users\\samee\\AppData\\Local\\Temp\\tempFile.txt";
DWORD attr = GetFileAttributesA(fileName);
if ((attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_READONLY))
SetFileAttributesA(fileName, attr & ~FILE_ATTRIBUTE_READONLY);
DeleteFileA(fileName);

trying to run commend on cmd throw c++ using createprocces (API)?

bool execute()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
bool flag = true;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
string f = "dir desktop"
if (CmdLine.parameter != "")
{
LPSTR l1 = const_cast<char *>(f.c_str());
CreateProcess(NULL, l1, NULL, NULL, false, 0, NULL, NULL, &si, &pi);
flag = true;
// WaitForSingleObject(pi.hProcess, INFINITE);
// // Close process and thread handles.
// CloseHandle(pi.hProcess);
// CloseHandle(pi.hThread);
//}
}
return flag;
}
I'm trying to run cmd command by visual studio.
I'm using createprocces (API) in order to run this thing
but I can't understand why it doesn't run anything.
dir is a command understood by cmd.exe, it's not a program you can execute.
You can try the command cmd /k "dir desktop", properly expressed as a C++ string.
E.g.,
auto execute()
-> bool
{
STARTUPINFO si = { sizeof( si ) };
PROCESS_INFORMATION pi = {};
string f = "cmd /k \"dir desktop\"\0";
bool const ok = !!CreateProcess( 0, &f[0], 0, 0, false, 0, 0, 0, &si, &pi );
if( !ok ) { return false; }
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return true;
}
Note how the calls to ZeroMemory have been replaced with C++ initialization.
Just by letting the compiler do its job you get shorter, more clear code that is more likely correct, and just as efficient (possibly more). Win win win.
Disclaimer: code not reviewed by compiler.
If the intent is to list the contents of the user's desktop folder, then note that dir desktop doesn't do that. As an interactive command in the command interpreter you could use dir %userprofile%\desktop, and that also works via the Windows Run-dialog. Depending on the command interpreter's behavior for command line arguments it may work directly via CreateProcess, or not.
Generally, when using Windows API level functions it's preferable to use the wchar_t-based text based functions, i.e. define UNICODE before including <windows.h> (or use the ...W functions explicitly).
If you call CreateProcess() with the first parameter set to NULL, then you have to make sure that l1 starts with the module name to call.
As dir is an internal command of the command processor and not an executable, you have to use cmd as module name and give the rest of the parameter as cmd expects them.
So try the following:
string f = "cmd /c=dir desktop";

Beginner C++ CreateProcess () Error 2

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.)

File re-direction operator ">" doesn't work with CreateProcess() API

I've a SupportApp.EXE which if I launch manually from windows CMD prommpt like this ::
SupportApp.EXE -t 100 > AFile.csv
works perfcetly fine & it generates a CSV file for me.
Now I want to automate same thing inside a VC++ code.
So, I use CreateProcess() API for this.
Code snippet below ::
TCHAR launcher[512];
_tgetcwd(launcher, _MAX_PATH);
TCHAR workDir[512];
_tgetcwd(workDir, _MAX_PATH);
_tcscat(launcher, "\\App\\SupportApp.exe");
TCHAR cmdlineoption[512];
_tcscpy(cmdlineoption, " -t 120 > AFile.csv");
LPTSTR appPath = (LPTSTR)cmdlineoption;
STARTUPINFO sInfo;
memset(&sInfo, 0, sizeof(sInfo));
sInfo.cb = sizeof(sInfo);
sInfo.dwFlags = STARTF_USESHOWWINDOW;
sInfo.wShowWindow = SW_SHOWMAXIMIZED;
PROCESS_INFORMATION pInfo;
memset(&pInfo, 0, sizeof(pInfo));
if (!CreateProcess(launcher, appPath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, workDir, &sInfo, &pInfo))
{
... // log error
}
// success
I see that CreateProcess() API succeeds and also i see that the -t 120 option I'm giving is also taken by this "SupportApp.exe"
BUT the file redirection operator ">" is not working with CreateProcess() API.
Instead the output is directed to CMD itself. But I want output to be sent to a CSV file.
Can anyone please help me in how do I redirect the output of my
"SupportApp.exe" to a file using CreateProcess() API from within my
VC++ code ?
UPDATE 2:
The inputs given by reviewers are incorporated in this & the modified code snippet is below which takes the file hnadle in STARTUPINFO structure as follows::
The file is getting created but the file is empty & it doesn't have any contents from createProcess()?
TCHAR launcher[512];
_tgetcwd(launcher, _MAX_PATH);
TCHAR workDir[512];
_tgetcwd(workDir, _MAX_PATH);
_tcscat(launcher, "\\App\\SupportApp.exe");
TCHAR cmdlineoption[512];
_tcscpy(cmdlineoption, " -t 120 > AFile.csv");
LPTSTR appPath = (LPTSTR)cmdlineoption;
STARTUPINFO sInfo;
memset(&sInfo, 0, sizeof(sInfo));
sInfo.cb = sizeof(sInfo);
sInfo.dwFlags |= STARTF_USESTDHANDLES; //newly added
sInfo.wShowWindow = SW_SHOWMAXIMIZED;
PROCESS_INFORMATION pInfo;
memset(&pInfo, 0, sizeof(pInfo));
sInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
sInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
HANDLE hn;
if(INVALID_HANDLE_VALUE != (hn = CreateFile(L"DoneDone.csv", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)))
{
sInfo.hStdOutput = =hn;
}
if (!CreateProcess(launcher, appPath, NULL, NULL, FALSE, 0, NULL, workDir, &sInfo, &pInfo))
{
... // log error
}
// success
Output redirection is a shell feature, i.e. the shell sets that up before starting the child.
You're not using a shell, instead going directly to the kernel asking it to start a process, so you don't get that service.
You need to set up the required redirection yourself. This is done in the STARTUPINFO's hStdOutput member. See the documentation, of course.
That's because the redirection operations (as well as the pipe operation) is part of the command prompt program, not part of the CreateProcess call.
However, you can do exactly what the command prompt program does when it does redirection, and set the file handles in the STARTUPINFO structure.

How to redirect in, out and err streams from process created with CreateProcess function? [duplicate]

I tried using CreateProcess to run a simple command like hg > test.txt. I tried running the string as a whole (as opposed to separating it into an application name and its parameters). Why does CreateProcess(0, "notepad.exe test.txt", ...) work but CreateProcess(0, "hg > test.txt", ...) does not?
The code below creates a console-less process with stdout and stderr redirected to the specified file.
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE h = CreateFile(_T("out.log"),
FILE_APPEND_DATA,
FILE_SHARE_WRITE | FILE_SHARE_READ,
&sa,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL );
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL ret = FALSE;
DWORD flags = CREATE_NO_WINDOW;
ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &si, sizeof(STARTUPINFO) );
si.cb = sizeof(STARTUPINFO);
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = NULL;
si.hStdError = h;
si.hStdOutput = h;
TCHAR cmd[]= TEXT("Test.exe 30");
ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
if ( ret )
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
return -1;
}
You can't use stdout redirection in the command line passed to CreateProcess. To redirect stdout you need to specify a file handle for the output in the STARTUPINFO structure.
You are also making another, more subtle, mistake. The second parameter, lpCommandLine must point to writeable memory because CreateProcess overwrites the buffer. If you happen to be using the ANSI version of the function then you will get away with this, but not for the Unicode version.
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
Microsoft has an example how to redirect the standard output:
http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx.
CreateProcess() launches processes, it is not a command line itnerpreter. It doesn't know what ">" is and won't do the stream redirection for you. You need to open the file test.txt yourself and pass the handle to it to CreateProcess inside the STARTUPINFO structure:
CreateProcess
STARTUPINFO
you should run process cmd.exe with params "/c command line".
This will redirect the output to a file or to organize a pipeline through CreateProcess.