Executing dos commands with Borland C++ and saving output - c++

New to C++.
I have been looking most of the afternoon, does anyone know a simple way to execute DOS commands and save to a variable for a windows forms application?

You can use system("dir"); . This will bring up the command prompt and run the dir command.
Alternatively you can use WinExec.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms687393(v=vs.85).aspx
You can make the command to redirect to a text file, and read off of it.

bool execDosCommand(char *command, AnsiString &output)
{
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa,sizeof(SECURITY_ATTRIBUTES));
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle=true;
sa.lpSecurityDescriptor=NULL;
HANDLE ReadPipeHandle;
HANDLE WritePipeHandle; // not used here
if(!CreatePipe(&ReadPipeHandle, &WritePipeHandle, &sa, 0))
return false;
STARTUPINFOA si;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb=sizeof(STARTUPINFO);
si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.wShowWindow=SW_HIDE;
si.hStdOutput=WritePipeHandle;
si.hStdError=WritePipeHandle;
PROCESS_INFORMATION pi;
ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
text cmd;
cmd.print("/c %s", command);
char pathbuf[MAX_PATH];
_searchenv("CMD.EXE", "PATH", pathbuf);
if(!CreateProcessA(pathbuf, cmd.t_str(), NULL, NULL, true, 0, NULL, NULL, &si, &pi))
return false;
char Data[1024];
for (;;)
{
DWORD BytesRead;
DWORD TotalBytes;
DWORD BytesLeft;
if(!PeekNamedPipe(ReadPipeHandle,Data,sizeof(Data),&BytesRead, &TotalBytes,&BytesLeft)) return false;
if(BytesRead)
{
if(!ReadFile(ReadPipeHandle,Data,sizeof(Data)-1,&BytesRead,NULL))
return false;
Data[BytesRead]='\0';
output += Data;
}
else
{
if(WaitForSingleObject(pi.hProcess,0)==WAIT_OBJECT_0)
break;
}
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(ReadPipeHandle);
CloseHandle(WritePipeHandle);
return true;
}
for example: execDosCommand("dir C:\", output);

as roymustang mentioned, you can use the system command to execute another command from the system. This could be a batch script for example that pipes the output of the command into a text file. You can then read the text file to actually get the information.
The Problem you have with "returning" the command output is, how does the command output look like? In what data structure would you store it? Most of the time you'll get a bunch of unformatted text, which can't be parsed to easily so there is no real generic way to return the output of an application or script into a C++ data structure.
You might as well want to take a look here:
http://docwiki.embarcadero.com/RADStudio/en/System,_wsystem
Like described above I don't believe there is a way to return the output of an application call to your program, at least none that I ever heard about.
Greets,
Florian

Related

How do I simulate user input to a console application from Unit Test project?

I am trying to write a text processing console application in C++ and I have met Windows API for the first time. But before defining a grammar or using the existing bison/flex or boost tools I want to realize a TDD approach and write all tests and interfaces (except here I have put a dummy test having hard time with even launching the .exe from test code).
My design is following:
- Unit tests from native test project call a CreateProcess() function from Windows API that I have put into CreateProc() macro. Example of this macro (I have slightly modified it) is taken from MSDN. Idea of this macro is execute my console application but from unit test to simulate user input after. Here is the code:
#define MYEXE L"my_Console_Application_Path.exe"
#ifdef MYEXE
PROCESS_INFORMATION CreateProc() {
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (CreateProcess
(
MYEXE,
NULL,
NULL,
NULL,
NULL, //,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi
)
)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return pi;
}
else
{
std::cout << "Unable to execute.";
return pi;
}
}
#endif
Test that runs and "uses" my console application is defined:
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(Should_Open_Console)
{
PROCESS_INFORMATION processInfo = CreateProc();
Assert::IsTrue(processInfo.dwProcessId); // check if process id is not zero
}
main function of console application looks like this:
int main()
{
std::cout << "test that function is running" << std::endl;
std::string myline = "";
std::getline(std::cin, myline);
return 0;
}
Basically my CreateProc() sucessfully launches the executable. However I want tests to simulate user input that main is listening to with getline(...). After I am going to parse this sequence with some parser.
How could I simulate this input within current console process? Of course I will be grateful if you can advise me some concrete instruments (is this SendInput() solution the best way to simulate input?) and the most important - how it should be done in terms of design? Ideally I see a string defined in a Unit test and passed through CreateProcess() as argument to main and the same string is somehow read from console after. Kind of this:
TEST_CLASS(UnitTest1)
{
public:
// parsing Hola as Hello
TEST_METHOD(Should_Return_Hello_If_Input_Equals_to_Hola)
{
CreateProc("Hola");
Assert::AreEqual(Console.readline() = "Hello"); // dummy code
}
Am I right? If yes, how could I actually do it? (if you can correct code snippets it would be great)

Using ShellExecute to send sqlite3.exe a shell script

I've got the following shell script in file c:/SQLiteData/Cmnds.txt
.open c:/SQLiteData/LGMeta.db
create table Temp {f INTEGER primary key};
insert into Temp values(-1);
.output c:/SQLiteData/Out.txt
select * from Temp;
I tried running it inside a c++ programme using
ShellExecute(NULL, L"open", L"c:/SQLiteData/sqlite3.exe",
L".read c:/SQLiteData/Cmnds.txt", NULL, 0);
ShellExecute returns 42 which suggests success but nothing happens. Neither Temp or Out.txt are created. Can anyone tell me what I'm missing?
EDIT
Thanks for the replies. I've spent the last 3 days tearing my hair out with this stuff. I patched this together from several posts on the subject
unsigned int RunCmnd(String CmndLine)
{
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
memset(&ProcessInfo,0,sizeof(ProcessInfo)); // setup memory blocks
memset(&StartupInfo,0,sizeof(StartupInfo));
StartupInfo.cb=sizeof(StartupInfo); // set structure size
StartupInfo.wShowWindow=SW_HIDE; // hide window
if (CreateProcess(NULL,CmndLine.c_str(),
NULL,NULL,false,0,NULL,NULL,&StartupInfo,&ProcessInfo))
{
WaitForSingleObject(ProcessInfo.hThread,INFINITE);
return 0;
}
else return GetLastError();
}
If I start up the command shell and enter the following line
c:/SQLiteData/sqlite3.exe < c:/SQLiteData/Cmnds.txt
everything works as expected BUT if use
RunCmnd("c:/SQLiteData/sqlite3.exe < c:/SQLiteData/Cmnds.txt")
from within my c++ builder app nothing happens. I'm missing something fundamental here. Can anyone tell me what?
Finally came up with this which was adapted from an excellent post by TarmoPikaro on this thread
How to execute a command and get output of command within C++ using POSIX?.
String TempFileName(bool ForwardSlash) // ForwardSlash default = true
{
wchar_t Nm[MAX_PATH],Path[MAX_PATH];
GetTempPath(MAX_PATH,Path);
if (!GetTempFileName(Path,L"",0,Nm))
throw Exception(String("TempFileName failed - ")+
SysErrorMessage(GetLastError()));
String Name=Nm;
if (ForwardSlash)
for (int Len=Name.Length(),i=1; i<=Len; i++) if (Name[i]=='\\') Name[i]='/';
return Name;
}
//---------------------------------------------------------------------------
String SQLiteExe(String DB,String OutFile,String Cmds)
{
// Returns first error message if process doesn't execute cleanly. Otherwise
// if OutFile=="" it returns the output
// if Outfile>"" the output is sent to OutFile and return is NULL.
String Output;
HANDLE hPipeRead,hPipeWrite;
SECURITY_ATTRIBUTES saAttr={sizeof(SECURITY_ATTRIBUTES)};
saAttr.bInheritHandle=TRUE; //Pipe handles are inherited by child process.
saAttr.lpSecurityDescriptor=NULL;
// Create a pipe to get output from child's stdout.
if (!CreatePipe(&hPipeRead,&hPipeWrite,&saAttr,0))
return "Error: Unable to create pipe";
STARTUPINFO si={sizeof(STARTUPINFO)};
si.dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdOutput=hPipeWrite;
si.hStdError=hPipeWrite;
si.wShowWindow=SW_HIDE;
// Prevents cmd window from flashing. Requires STARTF_USESHOWWINDOW in dwFlags.
TStringList *Batch=new TStringList;
Batch->StrictDelimiter=true;
Batch->Delimiter=';';
Batch->DelimitedText=Cmds;
if (OutFile>"") Batch->Insert(0,".output "+OutFile);
String S;
for (int i=0; i<Batch->Count; i++)
{
Batch->Strings[i]=Batch->Strings[i].Trim();
// .commands must have dot as first char on line
if (Batch->Strings[i]=="") continue;
S+=Batch->Strings[i]+(Batch->Strings[i][1]=='.' ? "" : ";")+"\r\n";
}
Batch->Text=S;
String BatchFile=TempFileName();
Batch->SaveToFile(BatchFile);
delete Batch;
String Cmd="sqlite3 "+DB+" \".read "+BatchFile+"\""; // assumes sqlite3.exe in PATH
PROCESS_INFORMATION pi={0};
BOOL fSuccess=CreateProcessW(NULL,Cmd.c_str(),NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
NULL,NULL, &si, &pi);
if (! fSuccess)
{
CloseHandle(hPipeWrite);
CloseHandle(hPipeRead);
DeleteFile(BatchFile);
return "Error: Failed to create process";
}
bool bProcessEnded=false;
while (!bProcessEnded)
{
// Give some timeslice (50ms), so we won't waste 100% cpu.
bProcessEnded=WaitForSingleObject(pi.hProcess,50)==WAIT_OBJECT_0;
// Even if process exited - we continue reading, if there is some data available
// over pipe.
while (true)
{
char buf[1024];
DWORD dwRead=0;
DWORD dwAvail=0;
if (!::PeekNamedPipe(hPipeRead,NULL,0,NULL,&dwAvail,NULL)) break;
if (!dwAvail) break; // no data available, return
if (!::ReadFile(hPipeRead,buf,std::min(sizeof(buf)-1,
(unsigned int)(dwAvail)),&dwRead,NULL) || !dwRead)
break; // error, the child process might ended
buf[dwRead]=0;
Output+=buf;
}
int p=Output.Pos("Error:"); // if (p) return first error message
if (p) {Output.Delete(1,p-1); Output.Delete(Output.Pos("\r\n"),Output.Length());}
}
DeleteFile(BatchFile); // NB can't be deleted until ProcessEnded
CloseHandle(hPipeWrite);
CloseHandle(hPipeRead);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return Output;
}
//---------------------------------------------------------------------------
Usage
String Err=SQLiteExe("c:/SQLiteData/MyDB.db","c:/SQLiteData/MyTblDump.txt"",
".mode csv; select * from MyTbl;");
if (Err>"") throw Exception(Err);
else ........
Multiple commands should be separated by semi-colons. SQLiteExe automatically removes the redundant semi-colons at the end of lines starting with a dot.

CreateProcess() works in cmd but if executed in cygwin

i'm working on a c++ project on windows, and i want to use cygwin not as a target environment, but just as a shell for replacing cmd, my project is actually compiled for windows with mingw.
My program for now just execute a CreateProcess, the problem is that if i call it from the cmd it works, if i execute the program from cygwin it does nothing while still the CreateProcess() is returning true.
That's the code:
int exec_module(const string& name, HANDLE stdIn, HANDLE stdOut, HANDLE stdErr) {
STARTUPINFO child_sinfo = { sizeof(child_sinfo) };
PROCESS_INFORMATION child_pinfo;
ZeroMemory(&child_sinfo, sizeof(child_sinfo));
child_sinfo.cb = sizeof(child_sinfo);
ZeroMemory(&child_pinfo, sizeof(child_pinfo));
child_sinfo.dwFlags = STARTF_USESTDHANDLES;
child_sinfo.hStdInput = stdIn;
child_sinfo.hStdOutput = stdOut;
child_sinfo.hStdError = stdErr;
return CreateProcess(0, _T((char *) name.c_str()), 0, 0, false,0, 0, 0, &child_sinfo, &child_pinfo);
}
And i call it like this:
if (!exec_module("caccone.exe", GetStdHandle(STD_INPUT_HANDLE), GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE))) {
cout << "Errore durante l'esecuzione del modulo" << endl;
}
I just can't figure out what's the problem.
My Bad here, to work well in cygwin i had to add synchronization code between parent and child, but the cmd shell worked also in a naife way.
Thx Harry Johnston for the point on the _T macro.

Reading from pipes blocks and deadlock

I am developing a remote shell like program. for running commands on remote machine I create a cmd.exe process and I redirect its stdin and stdout to a pair of pipes.
I use these pipes to send commands and get the result.
I used ReadFile function for returning the output of command from cmd.exe but I don't know the
exact amount of data that I must read from pipe. so if the data is not ready the readfile
goes to blocking mode and waiting for data.
I am using MSVC++ 2010 and my OS is Win7. Here is a part of my code as an example:
void CpipesDlg::OnBnClickedBtnredirstd()
{
char Cmd[]="dir *.*\r\n";
char Buff[129];
CString str;
HANDLE hStdIn_Read, hStdIn_Write;
HANDLE hStdOut_Read, hStdOut_Write;
SECURITY_ATTRIBUTES sAttr;
STARTUPINFOA StartInf;
PROCESS_INFORMATION procInf;
DWORD dwBytesToWrite,dwBytesReadFrom;
sAttr.nLength = sizeof(sAttr);
sAttr.bInheritHandle = TRUE;
sAttr.lpSecurityDescriptor = NULL;
CreatePipe(&hStdIn_Read,&hStdIn_Write,&sAttr,0);
CreatePipe(&hStdOut_Read,&hStdOut_Write,&sAttr,0);
//SetHandleInformation(hStdIn_Read, HANDLE_FLAG_INHERIT, 0);
//SetHandleInformation(hStdIn_Write, HANDLE_FLAG_INHERIT, 0);
memset(&StartInf,0, sizeof(StartInf));
memset(&procInf,0,sizeof(procInf));
StartInf.cb = sizeof(StartInf);
StartInf.dwFlags = STARTF_USESTDHANDLES;
StartInf.hStdError = hStdOut_Write;
StartInf.hStdOutput = hStdOut_Write;
StartInf.hStdInput = hStdIn_Read;
WriteFile(hStdIn_Write,Cmd,sizeof(Cmd),&dwBytesToWrite,NULL);
if(!CreateProcessA(NULL,"cmd.exe",NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW ,NULL,NULL,&StartInf,&procInf))
{
MessageBoxA(m_hWnd, "Can't Create Process","Error",MB_OK | MB_ICONERROR);
}
WriteFile(hStdIn_Write,Cmd,sizeof(Cmd),&dwBytesToWrite,NULL);
BOOL bSUCCESS =TRUE;
Sleep(100);
while(bSUCCESS)
{
BOOL bResult = ReadFile(hStdOut_Read,Buff,70,&dwBytesReadFrom,NULL);
if(!bResult)
{
break;
}
Buff[dwBytesReadFrom]=0;
str+= Buff;
bSUCCESS = dwBytesReadFrom!=0;
}
m_Disp = str;
UpdateData(FALSE);
CloseHandle(hStdIn_Read);
CloseHandle(hStdIn_Write);
CloseHandle(hStdOut_Read);
CloseHandle(hStdOut_Write);
}
In above code, in debugging mode the first calls to ReadFile function returns
true data but last call of it blocks, because there is no enough data to read.
Here is my Question:
How can I avoid the blocking mode or get the exact number of bytes for reading?
Regards!
You PROBABLY want to use the PeekNamedPipe function, which allows you to interrogate a pipe to see how much data there is available at any given time. If the lpBuffer is NULL then no data is being read.

How can I hide the window when I run a exe

I have this
static std::string exec(char* cmd) {
FILE* pipe = _popen(cmd, "r");
if (!pipe) return "ERROR -22";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
But the problem i have is that i want to hide the program that lunches how can I do that? thx
As Hans Passant mentioned in the comments, you have to use CreateProcess to spawn the child process instead of _popen, since _popen does not give you any control over the window creation process.
To hide the console window, use the CREATE_NO_WINDOW process creation flag for the dwCreationFlags parameter.
In order to capture the output of the process, you need to create a pipe for its standard output stream with CreatePipe. Assign that pipe handle to the hStdOutput member of the STARTUPINFO structure you pass in, and make sure to set the STARTF_USESTDHANDLES flag in the startup info's dwFlags so it knows that that member is valid. Then, to read data, you just use ReadFile on the pipe handle.
Hans also provided a link to a good example of creating pipes with a child process here, although that example is doing more than you need to do—it's creating pipes for all three streams (stdin, stdout, and stderr), whereas you only need to capture stdout.