How to automate perl script in Delphi?
Currently, I am working in a delphi application. I need to run perl script from the delphi application. To be more clear, manually we are executing the perl script in unix window. Now I need to automate the execution of that perl script from the application.
I tried using ShellExecute:
ShellExecute(Handle开发者_开发技巧, 'open', PChar('C:\loaderperl.bat'), nil, nil, SW_SHOW);
The window blinks for a second and closed. I don't know whether the script executed or not.
Hi, Thanks for all your answers and sorry for my late reply. Still I am struggling with this automation. Now I will explain the process clearly, at present I open the putty window, connect to the remote machine and execute the perl script. The perl script in turn calls an store procedure and updates the table. Now I want to do above explained process automatically by clicking a button. So when I click a button, it should call a function which connects to the remote machine and then executes the perl script. Am I clear to you??? Please help to solve this. I need this code in delphi
(Edited in response to comments below.)
There are a couple of steps to this: first, actually run the script; second, check if it successfully ran (both that it managed to start a new process and that that process succeeded.)
Part 1, running the script:
To run the script from your Delphi app, use ShellExecuteEx
with the "open
" verb should work (more details in flags below.) You could execute the script itself if it's associated with your Perl executable, or run your Perl exe with the script as a command line argument.
This article looks like a good starting point for using this API and its simpler cousin ShellExecute
.
The ShellExecute[Ex]
functions usually expect your application to run a message loop afterwards. It's unlikely your application isn't, so long as after the user clicks the button to start this your app sits idle, but if it isn't going to for some reason you should pass the SEE_MASK_NOASYNC
flag. MSDN has lots of info.
Part 2, checking if it executed successfully and succeeded in its task:
To see if the script executed, you should get a process handle to the started process and, if there was a new process, check the exit code from that. You should modify your script to return a non-zero code if its task fails. (I'm not familiar with Perl so I can't specifically tell you how, but generally it's the return value from the "main" function or other first/startup function.) You can do this by:
- Pass in the
SEE_MASK_NOCLOSEPROCESS
flag toShellExecuteEx
. That will fill thehProcess
member of the struct you pass in with a process handle, if it successfully started a process (if not, checkGetLastError
to find out why.) If this is all you need to know (just if it started, nothing about if it worked) then you're done. - Optional: wait for the process to end by using
WaitForSingleObject(YourParamStruct.hProcess, INFINITE)
(if you got a valid hProcess, of course) - Call
GetExitCodeProcess
to find the exit code. (Check for it returningSTILL_ACTIVE
, and if it is still running wait and try again.) Normally, it should exit with0
to indicate success. You should modify your script so that if something goes wrong it returns non-zero. You can make the codes as simple or complex as you want - eg, return1
for any error, or make a number of codes broken up by the type of error. (Avoid using259
, because that's the value ofSTILL_ACTIVE
- doing so might lead your Delphi code into an infinite loop, depending how it's coded, thinking it's still waiting to get an exit code because the Perl script is still running when it's not.)
Your Delphi app can then check this code to see if the Perl script worked or not and do something in response if it failed - log a message, tell the user, etc.
One other thing - you say you just want to know if the script executed or not and the above should provide that. Given it's a Perl script and runs on the command line, one other thing you might want to do is get its output, either to scan for errors if you don't return an error code, or to log or show the user. You can do this by running it via CreateProcess
and capturing the output. From what you say this is probably overkill for what you're after, though!
Start rsh or whatever your unix windows is with the relevant arguments (perl interpreter + script location+name) using shellexecute?
If you want to ShellExecute()
a batch file you need to execute cmd.exe
and pass the script as a parameter, like so:
ShellExecute(Handle, 'open', 'cmd.exe', '/C C:\loaderperl.bat', nil, SW_SHOW);
You can use output redirection to capture the script output in a file. If you want to see whether the script was executed successfully you can (for testing purposes) add pause
to the end of it.
You need to call external program (perl interpreter to execute on local machine, ssh or smth like this to execute on remote machine). Here is procedure that calls external program and waits until it ends (if you don't need to wait until it ends, remove WaitForSingleObject or just call ShellExecute as other people suggested).
UPDATE: To see script output, try to use solution from this article
function ExecAndWait(const FileName, Params: ShortString; const WinState: Word): boolean; export;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
CmdLine: ShortString;
begin
{ Put the name of file between quotes, due to spaces in names of files in system Win9x }
CmdLine := '"' + Filename + '" ' + Params;
FillChar(StartInfo, SizeOf(StartInfo), #0);
with StartInfo do
begin
cb := SizeOf(SUInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WinState;
end;
Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
{ Wait the finish of program }
if Result then
begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Free the Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end;
end;
精彩评论