Mysqldump via ShellExecute not working - delphi

I am trying to backup my mysql database from delphi by using ShellExecute to run mysqldump.
This is how I am using mysqldump:
MySqlDump.exe -u root -p[password] [databasename] > TheOutputFile.Sql
This works from command prompt.
I call this command line using ShellExecute:
ShellExecute(
0,
nil,
'cmd.exe',
'C:\SmartRetail\Test System\Periodic database backup\MySqlDump.exe -u root -p123 smartretailprogramdata > TheOutputFile2.Sql',
nil,
SW_SHOW
);
This does not work, instead it opens command prompt.
What am i doing wrong?

It opens the command interpreter because that's what cmd.exe is. You need to specify /C to tell the cmd process to close after it has interpreted your commands.
On top of that you need to take care of the working directory. Unless the .sql file is in the working directory, the dump process will not find it. And the working directory is inherited from the parent process since you did not specify it. You may need to specify the working directory.
Finally, ShellExecute is really the wrong solution here. You are only using it to get the stdout redirection. But that should really be done explicitly. Use CreateProcess instead.

Of curse you can :
var
BatFile : TStringList;
str: string;
const
EXEC = 'MySqlDump.exe -u root -p[password] [databasename] > TheOutputFile.Sql' ;
begin
BatFile := TStringList.Create;
BatFile.Text := EXEC ;
str := ExtractFilePath(Application.ExeName) + 's.bat';
BatFile.SaveToFile(str);
BatFile.Free;
ShellExecuteW(Handle, 'open', PWideChar(str), nil, nil, SW_HIDE);
Sleep(200);
ShowMessage('Done.');
DeleteFile(str);
end;

Related

How to execute a system command inside a informix stored procedure?

I need to execute a os command inside a informix SPL. My informix instance runs on Solaris machine. I tried with following codes. But gives below mentioned error.
Please correct me.
CREATE PROCEDURE log_message (message VARCHAR(70))
DEFINE os_command VARCHAR(100);
-- Output message to log file
LET os_command = 'ls -ltrh /informix/nuwan/' || message || ' >> /informix/nuwan/test/data.log';
SYSTEM os_command;
END PROCEDURE;
Then I called the procedure as follows
CALL log_message('Test message...');
it give below error
668: The system command cannot be executed or it exited with a non-zero status.
2: No such file or directory
Use the SYSTEM statement to issue an operating-system command from within an SPL routine.
https://www.ibm.com/support/knowledgecenter/en/SSGU8G_14.1.0/com.ibm.sqls.doc/ids_sqs_1358.htm

Inno Setup compilation fails with "Required parameter "Root" not specified." even when there is one

I'm a beginner about Inno Setup.
I want create an installer which copy two .exe files and append a value to the PATH environment variable.
Particularly I have to copy two executable files, called pandoc.exe and pandoc-citeproc.exe which are previously changed by me with visual studio developer prompt to don't have problem of Memory with large file conversions.
So I wrote this script with Inno Setup:
[Setup]
AppName=My Program
AppVersion=1.16.0.2
DefaultDirName={pf}\pandocX64
[Files]
Source: "pandoc.exe"; DestDir: "{app}";
Source: "pandoc-citeproc.exe"; DestDir: "{app}";
[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=yes
[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
ValueType: expandsz; ValueName: "PATH"; ValueData: "{olddata};{pf}\pandocX64";
Check: NeedsAddPath('{pf}\pandocX64')
[Code]
function NeedsAddPath(Param: string): boolean;
var
OrigPath: string;
begin
if not RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
'Path', OrigPath)
then begin
Result := True;
exit;
end;
// look for the path with leading and trailing semicolon
// Pos() returns 0 if not found
Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
end;
So, If I don't use the part of code to update the PATH variable, the installer copy the two executable files in C:\Program Files (x86)\pandocX64, and this is correct.
But I want also append that directory to the PATH system environment variable.
I read these threads:
How to set a global environment variable from Inno Setup installer?
How do I modify the PATH environment variable when running an Inno Setup Installer?
and I tried to write the code above.
Note that I put PATH as ValueName, and {olddata};{pf}\pandocX64 as ValueData to append to the current PATH value the directory in which the executable files are copied.
If I try to run this code, an error on line 17 is displayed
Required parameter "Root" not specified.
I think that Inno Setup expects the Root keyword in the line with code:
ValueType: expandsz; ValueName: "PATH"; ValueData: "{olddata};{pf}\pandocX64";
More precisely, I think that Inno Setup expects something like Inno Setup - Setting Java Environment Variable, but if I use that code, the PATH variable will be set to the {pf}\pandocX64 value, and no append operation will be performed.
Can someone help me?
Thank you
When you want to break a section entry to multiple lines for readability, you have to add \ at the end of the lines to escape the new-line character(s). A good practice is also to indent the lines, to make it clear to a human reader.
[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
ValueType: expandsz; ValueName: "PATH"; ValueData: "{olddata};{pf}\pandocX64"; \
Check: NeedsAddPath('{pf}\pandocX64')
Otherwise the Inno Setup compiler treats each line as a separate, and consequently an incomplete, entry.
I've corrected the answer to How do I modify the PATH environment variable when running an Inno Setup Installer? to include the \'s.

How do I Launch OpenFiles.exe from Delphi XE2 ShellExecute?

I need to launch MS Window's OpenFiles.exe from a Delphi XE2 application to export currently opened files to a text file. The normal cmd.exe syntax is something like:
Openfiles.exe /query /s 127.0.0.1 /nh >c:\OpenFilesExport.txt
Using the following code returns a successful exit code but the export file is not generated:
var
exInfo: TShellExecuteInfo;
exitcode: DWORD;
begin
FillChar(exInfo, Sizeof(exInfo), 0);
with exInfo do
begin
cbSize := Sizeof(exInfo);
fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
lpVerb := 'open';
lpFile := Pchar('Openfiles.exe');
lpParameters := PChar('/query /s 127.0.0.1 /nh >c:\OpenFilesOutput.txt');
nShow := SW_SHOWNORMAL
end;
if ShellExecuteEx(#exInfo) then
begin
while GetExitCodeProcess(exInfo.hProcess, exitcode)
and (exitcode = STILL_ACTIVE) do
Application.ProcessMessages();
CloseHandle(exInfo.hProcess);
end
else
ShowMessage(SysErrorMessage(GetLastError));
I've also tried putting the cmd.exe syntax in a bat file and launching that from shellexecute and it DOES generate the file but there is no content. Running the same bat file from explorer generates the file as expected.
How can I launch Openfiles.exe successfully from ShellExecute?
Your problem is the redirect, >, which only makes sense if you have a command interpreter. And in your code you do not. You have two options:
Call ShellExecuteEx passing a command interpreter to do the work.
Use CreateProcess to execute the other process, but pass a handle to a file as the stdout handle for the new process.
For the command interpreter option you would have a command line like this:
cmd /c Openfiles.exe /query /s 127.0.0.1 /nh >c:\OpenFilesExport.txt
The code might be like so:
FillChar(exInfo, Sizeof(exInfo), 0);
with exInfo do
begin
cbSize := Sizeof(exInfo);
fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
lpFile := 'cmd.exe';
lpParameters := '/c Openfiles.exe /query /s 127.0.0.1 /nh >c:\OpenFilesExport.txt';
nShow := SW_SHOWNORMAL;
end;
For the CreateProcess option you'll need to create the file with a call to CreateFile, and pass that handle as stdout of the new process. You'll need to make sure that the file handle is inheritable. And finally you'll need to wait on the process so that you can close the file handle.
Regarding your current code, your wait is not very pleasant. It's a busy wait that needlessly consumes CPU. You should use a blocking wait on the process handle.

How to use Delphi to execute a .bat file properly

I am running a .bat file from delphi(2010).
procedure TForm1.Button2Click(Sender: TObject);
var sCmd: String;
Begin
sCmd := Pwidechar('b4a_c2dm.bat' +' ' +'send ' + Trim(Edit1.Text)+' ' + Trim(edit2.Text ));
ShellExecute(0, 'open', 'b4a_c2dm.bat', PChar(sCmd), nil, SW_SHOWMAXIMIZED);
end;
This opens the cmd.exe and passes the correct string in the cmd.exe , BUT
Some how the line in the .bat file (java -cp b4a_c2dm.jar anywheresoftware.b4a.c2dm.C2DM %*) is showing up in the cmd.exe window and not letting the .bat file do its job.
Can someone help me with this.
In order to execute a batch file, the program to be called is 'cmd' and its parameter should be the name of the batch file.
Regarding your program,
ShellExecute (application.handle, 'open', 'cmd', PChar(sCmd), nil, SW_MAXIMIZE)

Send Parameter To CMD

How can i send parameters to CMD? for example send a path and start it from that path? How can i execute CMD commands?
Thanks
To start cmd.exe and immediately execute a command, use the /K flag:
procedure TForm1.FormCreate(Sender: TObject);
begin
ShellExecute(Handle, nil, 'cmd.exe', '/K cd C:\WINDOWS', nil, SW_SHOWNORMAL);
end;
To run a command in cmd.exe and then immediately close the console window, use the /C flag:
procedure TForm1.FormCreate(Sender: TObject);
begin
ShellExecute(Handle, nil, 'cmd.exe', '/C del myfile.txt', nil, SW_SHOWNORMAL);
end;
You can also use the Process class - see an example below
AProcess := TProcess.Create(nil); // Create process
AProcess.Executable := 'cmd'; // Executable to run
AProcess.Parameters.Add('/T:B0'); // Set background colour
AProcess.Parameters.Add('/K'); // Keep open
AProcess.Parameters.Add('title'); // A title for cmd
AProcess.Parameters.Add('My Console'); // Title
AProcess.Parameters.Add('&&'); // Start a new command line
AProcess.Parameters.Add('cd'); // Change directory
AProcess.Parameters.Add('D:\X\'); // Path to Folder
{Set environment variable}
AProcess.Parameters.Add('&&'); // Start a new command line
AProcess.Parameters.Add('HOME='+MYSQL_DIR); // Set env example
AProcess.Parameters.Add('&&'); // Start a new command line
AProcess.Parameters.Add('mysql.exe'); // run mysql.exe
AProcess.Parameters.Add('--host=' + VAR_HOST); // Parameter server
AProcess.Parameters.Add('--port=' + VAR_PORT); // Parameter mysql server port
AProcess.Execute; // execute detatched process command window remains visible
AProcess.Free; // free memory

Resources