How to pass parameters with spaces via cstdlib system - c++

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

Related

Opening excel files with system( ) on mac?

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.

Open .chm file at specific page/topic using command line arguments

I am attempting to open a .chm file(A windows help file) at a specific page/topic by using a system call in C++.
I can successfully open the .chm file to the start page through the following code, but how can I open a .chm file to a specific page/topic inside the help file?
system("start c:/help/myhelp.chm");
PS: I know system is evil/discouraged but the system part is not really relevant its the command line arguments I pass with the .chm file(that will specify what page I want to open) that I am trying to determine.
Ok the arguments are like so:
system(" /Q /E:ON /C HH.EXE ms-its:myChm.chm::myPageName.htm");
There is an API in the Windows SDK called HtmlHelp in the HtmlHelp.h file. You can call like so:
HtmlHelp(GetDesktopWindow(), L"C:\\helpfile\\::/helptopic.html", HH_DISPLAY_TOPIC, NULL);
The Microsoft Docs - HtmlHelpA function provides more information about the function. HtmlHelp() will normally resolve to HtmlHelpA() or HtmlHelpW() depending on whether Unicode compiler option is set or not.
See as well Microsoft Docs - HTML Help API Overview.
Another option - use ShellExecute. The Microsoft help is not easy to use. This approach is much easier and in line with your question. Here is a quick routine to open a help file and pass an ID number. I have just set up some simple char’s so you can see what is going on:
void DisplayHelpTopic(int Topic)
{
// The .chm file usually has the same name as the application - if you don’t want to hardcode it...
char *CmndLine = GetCommandLine(); // Gets the command the program started with.
char Dir[255];
GetCurrentDirectory (255, Dir);
char str1[75] = "\0"; // Work string
strncat(str1, CmndLine, (strstr(CmndLine, ".exe") - CmndLine)); // Pull out the first parameter in the command line (should be the executable name) w/out the .exe
char AppName[50] = "\0";
strcpy(AppName, strrchr(str1, '\\')); // Get just the name of the executable, keeping the '\' in front for later when it is appended to the directory
char parms[300];
// Build the parameter string which includes the topic number and the fully qualified .chm application name
sprintf(parms,_T("-mapid %d ms-its:%s%s.chm"), Topic, Dir, AppName);
// Shell out, using My Window handle, specifying the Microsoft help utility, hh.exe, as the 'noun' and passing the parameter string we build above
// NOTE: The full command string will look like this:
// hh.exe -mapid 0 ms-its:C:\\Programs\\Application\\HelpFile.chm
HINSTANCE retval = ShellExecute(MyHndl, _T("open"), _T("hh.exe"), parms, NULL, SW_SHOW);
}
The topics are numbered within your .chm file. I set up a #define for each topic so if I had to change the .chm file I could just change the include file to match and not have to worry about searching through the code for hardcoded values.

Fixing file permissions after modifying in C++?

I'm saving my data in the executable file of the program. I copy it to a temporary file, overwrite a part starting at a 'magic string' and rename it to the original. I know this is a bad idea, but I'm doing it just for experimenting.
I got everything to work so far, except for that I have to re-enable "Allow running as an executable" each time the file is replaced. What ways are there to solve this?
Additional information: I use linux.
If you want to avoid using system(), you can use
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
It is documented in http://linux.die.net/man/3/chmod.
See also: C++ - How to set file permissions (cross platform).
If you include stdlib.h, you can use system("command").
Try it:
system("chmod 755 yourExeFile")

opening an exe from current dir 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]);

Bash input/output in C++

I'm writing program in C++ (for XAMPP communication) and I want to execute command which I have in strings (I know that this is simply system("command")) but I want to get the output from bash to C++ to string. I've founded several threads about this, but no which solved Bash -> C++.
You can call the FILE *popen(const char *command, const char *mode) function. Then, you can read the file it returns to get the output of your call.
It's like using a pipe to redirect the output of the command you used to a file in the hard drive and then read the file, but you don't get to create a file in the hard drive.
The documentation of the popen() is here.
You need to call the popen function, and read the output from the FILE it returns.
You can try Standard Output Redirection to redirect the standard output to a file stream
and then use it to read to a string.
Dup()