2

For some back info to help you guys out, I'm making a small program that will take an .SQL file and restore it to the users localhost phpMyAdmin using mysql.exe. Importing the file through the MyAdmin itself by hand takes forever as it has to unzip and parse the information, this method is quicker and it's for my coworkers as we're always pushing backups and restores to our WAMP to experiment with.

My one issue I'm facing is that I can't seem to get it to change directories no matter what. I understand that wherever the executable was launched is the path that the system will inherit, so why can't I simply tell it to change directories?

Here's my code so far:

system("cd c:\wamp64\bin\mysql\mysql5.7.14\bin"); system("PAUSE"); system("dir"); system("PAUSE"); system("mysql.exe -u root -p dataBase < tables.sql"); 

Note: The pauses and system("dir") are in there strictly for testing purposes, once the window spits back the correct contents of the directory, then I know that it works and I'll only have the first and last lines left in the program.

UPDATE: I've been notified that every call to system creates a new CMD process which makes perfect sense as to why the cd will not effect anything, as it's opening a new process, changing directories, then on the next line it's calling a new process and pausing that. What would be the workaround for this?

UPDATE 2: I decided to join multiple commands together using && but that limits me on the usability and "styling" side of things, but that's not a problem, the program is needed as a run & done type of deal.

Here's what I've come up with:

system("cd c:\\wamp64\\bin\\mysql\\mysql5.7.14\\bin && mysql.exe -u root -p dataBase < table.sql"); cout << "\n" << "The database 'dataBase' has been restored using 'table.sql' successfully!" << "\n\n"; return 0; 

Are there any advantages to creating a .cmd file and running it using CreateProcess() or disadvantages to using the method that I've come up with?

Note: The database name and .sql files aren't pulled from anything, the names will be static so I don't have to worry about updating that.

10
  • msdn.microsoft.com/en-us/library/windows/desktop/aa365530 Commented Jun 14, 2017 at 20:38
  • 3
    Please don't use system. It has so, so, many issues... Commented Jun 14, 2017 at 20:41
  • 1
    1. Didn't you get a warning about bad escape sequences? 2. each call to system opens a new command session.As a result the cd has no effect. Commented Jun 14, 2017 at 20:42
  • What would be the workaround for this? Do everything in one system() call. Commented Jun 14, 2017 at 20:48
  • Lookup && in your cmd.exe reference. Commented Jun 14, 2017 at 20:49

2 Answers 2

4

A better idea is to dynamically generate a batch file (.cmd or .bat, there are slight differences) and then invoke that with cmd.exe /c batchFile.cmd:

#include <cstdlib> #include <cstdio> ofstream batch_file; batch_file.open( "commands.cmd", ios::trunc ); batch_file << "cd c:\\wamp64\\bin\\mysql\\mysql5.7.14\\bin" << endl << "PAUSE" << endl << "dir" << endl << "PAUSE" << endl << "mysql.exe -u root -p dataBase < tables.sql" << endl; batch_file.close(); int batch_exit_code = system( "cmd.exe /c commands.cmd" ); // blocks until the child process is terminated if( batch_exit_code != 0 ) { cout << "Batch file exited with code " << batch_exit_code << endl; } remove( "commands.cmd" ); // delete the batch file 

This has the benefit of allowing you to customize the text and commands, such as performing your own detection of the location of the MySQL binaries and your temporary files.

Note that if you're always running on Windows, you might want to use CreateProcess instead, as system has some overheads:

system() and CreateProcess() / CreateProcessW()

The system function passes command to the command interpreter, which executes the string as an operating-system command. system refers to the COMSPEC and PATH environment variables that locate the command-interpreter file (the file named CMD.EXE in Windows NT).

As you want to run cmd.exe directly, this would result in it opening twice.

You can use CreateProcess instead:

STARTUPINFO info={sizeof(info)}; PROCESS_INFORMATION processInfo; if( CreateProcess( "cmd.exe", "/c commands.cmd", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo ) ) { WaitForSingleObject( processInfo.hProcess, INFINITE ); CloseHandle( processInfo.hProcess ); CloseHandle( processInfo.hThread ); } 
Sign up to request clarification or add additional context in comments.

4 Comments

Excellent information! I read up on the CreateProcess, seems like a more viable option over calling the system to open, well, the system. Now wouldn't this cause problems as that command.cmd file will always remain? Or will every iteration simply overwrite the previous one?
@Brian I amended my code to delete the file after the file is executed.
Thank you so much man! You guys are amazing, 15 minutes in and I've got more information than I literally asked for! I'll do my best to help others out where I can. Back on topic, I've updated my original post, are there any upsides to using CreateProcess() over my single call to system?
2nd code sample doesn't work at all. See the description of CreateProcess() parameter lpApplicationName: In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path.
3

Here is a way you can execute system with directory change:

// using AND_CMD like an operator to concat commands -- you can also just type it in one string: "edit & shutdown -h"... // this works in c, too, but no dynamic variables are possible //#define AND_CMD " & " // c++ #define AND_CMD +" & "+ system( "cd c:\wamp64\bin\mysql\mysql5.7.14\bin" AND_CMD "PAUSE" AND_CMD "dir" AND_CMD "PAUSE" AND_CMD "mysql.exe -u root -p dataBase < tables.sql" ); 

So you only need to join the commands with the string " & ". If you need to run the code on conditions to the program itsself/keep the directory by next time calling the system-function, you should look for alternatives or you pipe the commands into the commandprompt (eg. running your program by myprogram.exe | %comspec% and invoking the commands by outputting with eg. printf.

2 Comments

Or just to keep shure: #define AND_CMD +string(" & ")+
I don't really see the reason for that macro.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.