opening an exe from current dir C++ - c++

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

Related

Can't open a file in C/C++ using eclipse cdt

I have a medium size program I'm developing using eclipse, I can't show the content because it would be too large. At some point I have some lines of fopen, I'm basically trying to create a new file and printing inside such file a content that has been derived from some processing.
So my line is something like a classic
FILE* f = fopen(filename,"w");
where filename is a char array large enough. However the FILE* returned is 0, and when I check the errno it is number 2, which means that the file doesn't exists.
However that's the point, I was trying to create a new file.
Is there something you could suggest that can I further check?
It's worth to note I'm running this stuff on unix, not windows.
Is the value of filename an absolute path or a relative one? If it's the latter, then probably the process you run hasn't the cwd (current working directory) you think it has.
Try using an absolute path, if that works then
use the chdir system call at the begin of main to set the cwd
Your filename might be incorrectly built, or you have no access to the path, or parts of the path don't exist.
Try a simple and clearly legal path first, like C:\\Temp\\x.x or something similar. if this works, it is not your code, but the filename.

A system function to convert relative path to full path that works even for non-exsting paths?

This question has been asked before, but pretty much all the answers boil down to the realpath function. Which doesn't work for paths that do not exist. I need a solution that will, and I want to call a POSIX or OS X framework function rather than hand-parse strings.
To reiterate: I need a function that takes an arbitrary path string and returns the equivalent path with no "./" or ".." elements.
Is there such a solution?
Are you sure there can be such a solution? I believe that not (because some directories could be typos or symbolic links to be created).
What do you expect your betterrealpath function to return for /tmp/someinexistentdirectory/foobar ? Perhaps the user intent was a symbolic link from his $HOME to /tmp/someinexistentdirectory ? Or perhaps it is a typo and the user wants /tmp/someexistentdirectory/foobar ...? And what about /tmp/someinexistentdirectory/../foobar? Should it be canonicalized as /tmp/foobar? Why?
Maybe using first dirname(3), then doing realpath(3) on that, then appending the basename(3) of the argument should be enough? In C something like:
const char*origpath = something();
char*duppath = strdup(origpath);
if (!duppath) { perror("strdup"); exit(EXIT_FAILURE); };
char*basepath = basename(duppath);
char*dirpath = dirname(duppath);
char*realdirpath = realpath(dirpath, NULL);
if (!realdirpath) { perror("realpath"); exit(EXIT_FAILURE); };
char* canonpath = NULL;
if (asprintf(&canonpath, "%s/%s", realdirpath, basepath) <= 0)
{ perror("asprintf"); exit(EXIT_FAILURE); };
free (duppath), duppath = NULL;
basepath = NULL, dirpath = NULL;
/// use canonpath below, don't forget to free it
Of course that example won't work for /tmp/someinexistentdirectory/foobar but would work for /home/violet/missingfile, assuming your home directory is /home/violet/ and is accessible (readable & executable) ...
Feel free to improve or adapt to C++ the above code. Don't forget to handle failures.
Remember that i-nodes are central to POSIX filesystems. A file (including a directory) can have one, zero, or several file paths... A directory (or a file) name can be rename-d by some other running process...
Perhaps you want to use a framework like Qt or POCO; they might provide something good enough for you...
Actually, I suggest you to code your betterrealpath function entirely yourself, using only syscalls(2) on Linux. You'll then have to think about all the weird cases... Also, use strace(1) on realpath(1) to understand what it is doing...
Alternatively, don't care about non-canonical paths containing ../ or symbol links in directories, and simply prepend the current directory (see getcwd(3)) to any path not starting with / .......

Accessing resources from program in Debian package structure

I've made a DEB package of an C++ app that I've created. I want this app to use resources in the "data" directory, which, in my tests (for convenience), is in the same location that the program binary, and I call it from inside the code by its relative path. In the Debian OS there are standard locations to put the data files in (something like /usr/share/...), and other location to put the binaries in (probably /usr/bin). I'd not like to put the paths hard-coded in my program, I think its a better practice to access an image by "data/img.png" than "/usr/share/.../data/img.png". All the GNU classic programs respect the directories structure, and I imagine they do it in a good manner. I tried to use dpkg to find out the structure of the apps, but that didn't help me. Is there a better way that I'm doing to do this?
PS: I also want my code to be portable to Windows (cross-platform) avoiding using workarounds like "if WIN32" as much as possible.
In your Debian package you should indeed install your data in /usr/share/. When accessing your data, you should use the XDG standard, which states that $XDG_DATA_DIRS is a colon-separated list of data directories to search (also, "if $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used.").
This is not entirely linux specific or debian specific. I think is has something to do with Linux Standard Base or POSIX specifications maybe. I were unable to discover any specification quickly enough.
But you should not use some "base" directory and subdirectories in it for each type of data. Platform dependent code should belong into /usr/lib/programname, platform independent read-only data into /usr/share/programname/img.png. Data changed by application in /var/lib/programname/cache.db. Or ~/.programname/cache.db, depends what kind of application it is and what it does. Note: there is no need to "data" directory when /usr/share is already there for non-executable data.
You may want check http://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html if packaging for Debian. But it is not resources like in adroid or iphone, or windows files. These files are extracted on package install into target file system as real files.
Edit: see http://www.debian.org/doc/packaging-manuals/fhs/fhs-2.3.html
Edit2: As for multiplatform solution, i suggest you make some wrapper functions. On windows, it depends on installer, usually programs usually have path in registry to directory where they are installed. On unix, place for data is more or less given, you may consider build option for changing target prefix, or use environment variable to override default paths. On windows, prefix would be sufficient also, if it should not be too flexible.
I suggest some functions, where you will pass name of object and they will return path of file. It depends on toolkit used, Qt library may have something similar already implemented.
#include <string>
#ifdef WIN32
#define ROOT_PREFIX "c:/Program Files/"
const char DATA_PREFIX[] = ROOT_PREFIX "program/data";
#else
#define ROOT_PREFIX "/usr/"
/* #define ROOT_PREFIX "/usr/local/" */
const char DATA_PREFIX[] = ROOT_PREFIX "share/program";
#endif
std::string GetImageBasePath()
{
return std::string(DATA_PREFIX) + "/images";
}
std::string GetImagePath(const std::string &imagename)
{
// multiple directories and/or file types could be tried here, depends on how sophisticated
// it should be.
// you may check if such file does exist here for example and return only image type that does exist, if you can load multiple types.
return GetImageBasePath() + imagename + ".png";
}
class Image;
extern Image * LoadImage(const char *path);
int main(int argc, char *argv[])
{
Image *img1 = LoadImage(GetImagePath("toolbox").c_str());
Image *img2 = LoadImage(GetImagePath("openfile").c_str());
return 0;
}
It might be wise to make class Settings, where you can initialize platform dependent root paths once per start, and then use Settings::GetImagePath() as method.

Use a personal program in Firebreath

I'm building a plugin using Firebreath. I made a personal method in ABCPluginAPI.cpp called exe_program() and I would like to call another program using popen called my_program. All the files are into firebreath/projects/ABCPlugin/.
My method is:
string ABCPluginAPI::exe_program()
{
FILE * pPipe;
fd_set readfd;
char buff[1024];
char command[128];
int ret;
strcpy(command, "my_program");
if (!(pPipe = popen(command, "r"))) {
// Problem to execute the command
return "failed";
}
while(fgets(buff, sizeof(buff), pPipe)!=NULL){
cout << buff;
return buff;
}
}
The problem I have is that the plugin is not running my_program, actually if I execute the pwd command, it shows my $HOME directory. pwd works because is a general command but I don't want to put my program into $PATH variable because this plugin must be portable.
Probably Firebreath use a special directory to refer to this kind of files or something similar.
You probably need to specify a full path and filename of the application you want to run; the current working directory is not garanteed to always be the same value.
From the Tips and Tricks page of firebreath.org there is code you can add to your PluginCore-derived object that will give you the full path and filename of your plugin file:
// From inside your Plugin class (that extends PluginCore)
std::string MyPlugin::getFilesystemPath()
{
return m_filesystemPath;
}
You can take that path, strip off the last part, and change it to your executable filename; as long as you place the executable in the same directory as your plugin that should work fine. Alternately you could install it in some other well-known location.
Note that to call a method on your main Plugin object from your JSAPI object there should be a helper method getPlugin() on your JSAPI object (if you used fbgen to generate it):
std::string pluginPath = getPlugin()->getFilesystemPath();
Hope that helps

How to pass parameters with spaces via cstdlib system

I have this windows console app which takes a file, do some calculations, and then writes the output to a specified file. The input is specified in "app.exe -input fullfilename" format. I need to call this application from my C++ program, but I have a problem with spaces in paths to files. When I call the app directly from cmd.exe by typing (without specifying output file for clarity)
"c:\first path\app.exe" -input "c:\second path\input.file"
everything works as expected. But, when I try using cstdlib std::system() function, i.e.
std::system(" \"c:\\first path\\app.exe\" -input \"c:\\second path\\input.file\" ");
the console prints out that c:\first is not any valid command. It's probably common mistake and has simple solution, but I have been unable to find any. Thx for any help.
Instead of std::system(), you should use the _wspawnv function from the Windows API. Use _wspawnvp if you want to search for the program in PATH, rather than specifying a full path to it.
#include <stdio.h>
#include <wchar.h>
...
const WCHAR *app = L"C:\\path to\\first app.exe";
const WCHAR *argv[] = {app, L"-input", L"c:\\second path\\input file.txt"};
_wpspawnv(_P_WAIT, app, argv);
You could also use _spawnv / _spawnvp if you are 100% sure that your input filename will never, ever contain anything else than ASCII.
Don't try to put the quotes in the std::system() call. Try the following:
std::system("c:\\first\\ path\\app.exe -input c:\\second\\ path\\input.file");