I am trying to get my C++ program to open up an existing Excel spreadsheet (along with a bunch of applications), however it keeps returning an error that a file does not exist. I am using the following code:
int main(){
system("open ~/path/file");
//--open applications using same command--//
}
The file is definitely there and this command works to open all the applications, so I'm not sure what I am doing wrong.
Thanks in advance!!
Very probably, the system /bin/sh -which by definition is used by system(3)- does not expand ~.
You might try something like
char cmd[256];
snprintf(cmd, sizeof(cmd), "open %s/path/file", getenv("HOME"));
if (0 != system(cmd))
{ fprintf(stderr, "%s failed\n", cmd); exit(EXIT_FAILURE); };
since interactive shells usually expand ~ as $HOME and HOME is generally an environment variable.
(With C++, you could use std::string operations instead of snprintf)
My snprintf + system trick is not at all failproof. If $HOME contains spaces or bizarre characters like ; or ', it wont work. And snprintf itself might fail (e.g. because $HOME is huge).
Of course, you'll better test before that getenv("HOME") is not NULL. You might use getpwuid(3) with getuid(2) if getenv("HOME") fails by returning NULL.
On Linux you probably want xdg-open instead of open.
Related
Basically, is there a simple way to get a list of all bash commands in the PATH environment variable in C++? My current solution is to run a command beforehand that lists all the commands into a .txt, which is then read into the C++ program. I want to be able to cut out this step, if possible.
ls ${PATH//:/ } > commands.txt
If you do NOT need to use stdin in your C++ program
This is the easy solution. Just pipe the output of the ls command to your C++ program. Then, in your C++ program, read the contents of the file from stdin like you would read from a normal file. Literally use stdin wherever you need to provide a file descriptor. So, your command would look something like
ls ${PATH//:/ } | ./a.out
The | denotes a pipe in bash. It takes stdout from the first program (here ls) and redirects it to stdin of the second program (here your C++ program).
If you do need to use stdin in your C++ program
This is going to be tricky. You essentially need to make your C++ program do everything itself. The first way to this that comes to mind is
Read $PATH using getenv().
Parse $PATH by replacing all occurrences of : with (a blank space). This is easy enough to do in a loop, but you could also use std::replace.
Now that you have the directory paths from $PATH, you simply need the contents of each directory. This post will help you get the contents of a directory.
UPDATE: Another Approach
I've thought of another way to approach your problem that allows you to use IO redirection (ie. use the pipe), and also use stdin at the same time. The problem is that it is probably not portable.
The basic idea is that you read the output of ls from stdin (using the pipe operator in bash). Next, you essentially reset stdin using freopen. Something along the lines of
#include <stdio.h>
int main(void)
{
char buf[BUFSIZ];
puts("Reading from stdin...");
while(fgets(buf, sizeof(buf), stdin))
fputs(buf, stdout);
freopen("/dev/tty", "rw", stdin);
puts("Reading from stdin again...");
while(fgets(buf, sizeof(buf), stdin))
fputs(buf, stdout);
return 0;
}
The above code is from here. It reads stdin, resets stdin, and reads from stdin again. I would suggest not using this approach for anything important, or for something that needs to work on several platforms. While it is more convenient since it allows you to use IO redirection while retaining the ability to use stdin, it is not portable.
On my home Linux laptop, I like to write wrapper programs and GUI helpers for things I use frequently. However, I don't like Bash scripting very much, so I do a lot of stuff in C++. However, a lot of times, this requires me to use the system() function from the cstdlib.
This system() command is awesome, but I wanted a way to call system() and receive the stdout/stderror. The system() command only returns the return code from the command. So, in a Bash script, one can do:
myVar=$(ls -a | grep 'search string')
echo $myVar
and myVar will output whatever the stdout was for the command. So I began writing a wrapper class that will add a pipe-to-file to the end of the command, open the file, read all of the piped stdout, and return it as either one long string or as a vector of strings. The intricacies of the class are not really relevant here (I don't think anyway), but the above example would be done like this:
SystemCommand systemCommand;
systemCommand.setCommand("ls -a | grep \'search string\' ");
systemCommand.execute();
std::cout << systemCommand.outputAsString() << std::endl;
Behind the scenes, when systemCommand.execute() is called, the class ensures that the command will properly pipe all stdout/stderr to a randomly generated filename, in the current working directory. So for example, the above command would end up being
"ls -a | grep 'search string' >> 1452-24566.txt 2>&1".
The class then goes attempts to open and read from that file, using ifstream:
std::ifstream readFromFile;
readFromFile.open(_outputFilename);
if (readFromFile.is_open()) {
//Read all contents of file into class member vector
...
readFromFile.close();
//Remove temporary file
...
} else {
//Handle read failure
}
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory? If so, what would be a way to make it more robust (specifically on Linux)?
A side/secondary question: Is there a very simplified way to achieve what I'm trying to achieve without using file pipes? Perhaps some stuff available in unistd.h? Thanks for your time.
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory?
Yes.
Mount a USB thumb drive (or some other removable media)
cd to the mount
Execute your program. While it's executing, remove the drive.
Watch the IO error happen.
There's a ton of other reasons too. Filesystem corruption, hitting the file descriptor limit, etc.
If so, what would be a way to make it more robust (specifically on Linux)?
Make temporary files in /tmp, whose entire purpose is for temporary files. Or don't create a file at all, and use pipes for communication instead (Like what popen does, like harmic suggested). Even so, there are no guarantees; try to gracefully handle errors.
i implemented program of network statistics with help of powershell scrpit. the program is running successfully and giving me perfact output as well . below is my program.
int main(int argc, char *argv[])
{
string strPath = "C:\\Get-NetworkStatistics.ps1";
char str[50] = "C:\\Get-NetworkStatistics.ps1";
char command[500];
//access function:
//The function returns 0 if the file has the given mode.
//The function returns –1 if the named file does not exist or does not have the given mode
if(access(strPath.c_str(),0) == 0)
{
_snprintf(command, sizeof(command), "Start Powershell.exe -noexit Set -executionpolicy;.'%s';Get-NetworkStatistics",str);
system(command);
}
else
{
system("cls");
cout << "File is not exist";
system("pause");
}
return 0;
}
! here is the output of above program
as you can see the output is in the powershell windows.. i want to fetch all this data of powershell output and want to display it in console. how should it possible?
please help me..
Unless you need to do display the info in realtime as it becomes available, just redirect it to a file, then read that file from C++.
Since netstat was lobotomized in Windows XP SP 2 or thereabouts I can understand using Powershell.
But it may just be that netstat will serve your needs, and then you don't have to deal with any of that complication.
By the way, I recommend using a scripting language for scripting tasks. There is of course the complication that Powershell scripting is disabled by default, otherwise using the Powershell scripting facility would be indicated. But e.g. in this case a [cmd.exe] batch file would be more natural than doing its job from C++.
The Windows Script Host shell objects, available from JScript and VBScript, provide functionality for process execution with output grabbing.
There is a little snag in that you then have to poll the output, but I think it's still easier than doing this at the C/C++ API level.
I wrote a program in python that has the functionality of being able to find out file sizes, create directories, and move around as though i'm just in a regular shell. The porblem is that I need to be able to do this in c++.
Here's the python code that I need c++ functionality from:
os.chdir('r'+str(r)+'n'+str(n))
def build_path(newpath):
if os.path.isdir(newpath):
os.chdir(newpath)
else:
os.mkdir(newpath)
os.chdir(newpath)
And also this piece:
if os.stat('data'+str(tick)).st_size > 2500000:
heavyFile.close()
tick+=1
heavyFile=open('data'+str(tick),'w')
os.system('touch COMPLETED'+str(r)+str(n))
So basically I need to be able to make some directories, change into those directories, build files, but don't let them get much larger than 2.5 MB, and when they finally get over that size, create a new file that is incremented by one.
so the file tree ends up looking like:
r4n4/dir1/data0,data1,data2,etc
r4n4/dir2/data0,data1,data2,etc
and so on.
How can I do this in c++?
I know I can call system('command')
but I don't know how to get file size nicely using that and I'm just hoping for an easier way to do this.
Also, I do not have access to boost where I am running this program.
Try checking out the boost::filesystem library. (http://www.boost.org/doc/libs/1_54_0/libs/filesystem/doc/index.htm) All three of your requests are covered in the tutorial.
You can use stat() in your code to get properties of filesystem objects. Here's an example:
#include <sys/types.h>
#include <sys/stat.h>
struct stat buf;
stat(filename, &buf);
// If it's a regular file, print the size in bytes
if ((buf.st_mode & S_IFREG) == S_IFREG)
{
off_t size = buf.st_size;
fprintf(stdout, "%s is a regular file\n", filename);
fprintf(stdout, "%s is a regular file: size %zd bytes\n", filename, size);
}
There are also macros within stat.h which make it a little easier to check if something is a regular file or whatever, instead of AND'ing multiple things as above. For example, the S_ISREG macro will do the same thing as the code above:
if(S_ISREG(buf.st_mode)) /* stat.h macro, instead of AND'ing */
{
fprintf(stdout, "%s is a regular file\n", filename);
}
The macro S_ISDIR would tell you if it's a directory. There are other macros like this.
You can do man -s 2 stat to see the man page for stat() and get more details. Hope this helps.
You can make use of system calls to achieve what you want. If you are on Linux, check out the following man pages:
man 2 chdir
man 2 mkdir
man 2 stat
You can also just call your script from your c++ code with this command:
system ("python script.py");
I have the python code... but how do i do it in c++?
I don't have much experience with c++. What i want is to make an exe that will be put as autorun in an cd. It has to open the application.ini file in my cd with xulrunner.exe in my cd. As the path will vary in each computer i hav to do something like this.
import subprocess
import os
path= os.getcwd()
final = path + '/xulrunner.exe ' + path + '/application.ini'
print final
os.system('final')
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe'])
I'm not completely sure I understand what you're asking, but you may want the 'system' function. This will invoke the platform's command processor to execute the command given.
If all of your files (xulrunner.exe and application.ini) are in the same directory as the auto-run executable, you should be able to just rely on the working directory being correct and not need to give a full path.
For example:
system("xulrunner.exe application.ini");
os.system() is system(), in Win32 getcwd() is GetCurrentDirectory()
http://msdn.microsoft.com/en-us/library/aa364934(VS.85).aspx
Probably should stick to char buffers for strings. So, something like (untested, untried)
#include <stdio.h>
int main(int ac, char **av) {
char path[MAX_PATH+1];
GetCurrentDirectory(MAX_PATH, path);
char final[MAX_PATH * 2 + 100];
sprintf(final, "%s /xulrunner.exe %s/application.ini", path, path);
printf("%s", final);
system(final);
// not sure what the notepad call is for, probably another system call
return 0;
}
It depends on the platform you're implementing it for, but on Windows (assuming from the C:\ that's where you are), you'll need to dip into the Windows API and use CreateProcess. On Linux, it would be system or popen (not terribly familiar there).
http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx
If the EXE you're running is known to be in the current working directory (wherever your program is started from), you can simply use the filename ("xulrunner.exe") as the name. You may be safer with ".\xulrunner.exe", but that's more preference. You can also specify a subdirectory, or even SetCurrentDirectory to move to another dir.
BOOL startedProgram = CreateProcess("xulrunner.exe", "application.ini", [fill in other options as you need]);