Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Running another program then retrieving a value


  • Please log in to reply
11 replies to this topic
fooz
  • Members
  • 8 posts
  • Last active: Feb 23 2006 09:03 AM
  • Joined: 08 Jan 2006
I have the following ahk script that is supposed to execute my php program, passing the value 5. Then the ahk script should receive a single value from the program.

None of the 3 methods I've tried (based on various threads I've read) seem to work. Help appreciated. And I'll admit I'm a total newb with this stuff.

Here' the ahk:

#SingleInstance

; 1st method
/*
ErrorLevel = 999

RunWait, C:\php\php.exe getVPIP.php 5, ,Hide UseErrorLevel

MsgBox, Result: %ErrorLevel%
*/


; 2nd method
/*
ret1 := CMDret("C:\php\php.exe getVPIP.php 5")

MsgBox, Result: *%ret1%*

CMDret(CMD)
{
  VarSetCapacity(StrOut, 10000)
  RetVal := DllCall("cmdret.dll\RunReturn", "str", CMD, "str", StrOut)
  Return, %StrOut%
}
*/


; 3rd method
CMDout=
CMDerr=
ProgramName := "C:\php\php.exe getVPIP.php 5"

Ret := RunWaitEx(ProgramName, NULL, TextIn, CMDout, CMDerr)
MsgBox, Return Value: %Ret% `r`n`r`nStdError: `r`n%CMDerr%`r`nStdOutput: `r`n%CMDout%

RunWaitEx(CMD, CMDdir, CMDin, ByRef CMDout, ByRef CMDerr)
{
  VarSetCapacity(CMDOut, 100000)
  VarSetCapacity(CMDerr, 100000)
  RetVal := DllCall("cmdret.dll\RunWEx", "str", CMD, "str", CMDdir, "str", CMDin, "str", CMDout, "str", CMDerr)
  Return, %RetVal%
}

And here's the PHP (super simple):
<?

$inputVar = $argv[1];

// perform logic based on input, then return value

// trying 3 different methods to return a value
echo 3;
return 4;
exit(5);

?>


toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
There is one obvious bug, so I do not search further. Please test if that is the problem. Anyway, please give feedback.

When you want a value to be returned from a function, you have to use no %. This this line
Return, %var%
has to be
Return, var
This is wrong in method 2 and 3.

Method 1 will not work since the ErrorLevel will not contain the output of the command you run, but if the run command could be run. You have to use a pipe "|" and cb.exe to achieve it.

And please use the [ code] [ /code] tags to format your posts. This helps us to read your post.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

fooz
  • Members
  • 8 posts
  • Last active: Feb 23 2006 09:03 AM
  • Joined: 08 Jan 2006
Thanks for the reply.

Changing the return syntax as you suggest doesn't seem to matter. I think the nuance may be whether or not you follow Return with a comma.
Return, %RetVal%

...as opposed to...
Return RetVal

I was copying and pasting code directly from corrupt, who seems to know what he's doing. The code came from this post on CMDret: http://www.autohotke...opic.php?t=3687


And I attempted method 1 based on this statement in the AutoHotKey Help manual:

UseErrorLevel: UseErrorLevel can be specified alone or in addition to one of the above words (by separating it from the other word with a space). When the launch fails, this option skips the warning dialog, sets ErrorLevel to the word ERROR, and allows the current thread to continue. If the launch succeeds, RunWait sets ErrorLevel to the program's exit code, and Run sets it to 0.



toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
You are right. It seams to me that the StrOut is a pointer, so the %% are needed. But I'm not sure, since I do not know much about about DllCall.

Regarding method 1 you might be right.

I have now idea what is wrong. Sorry.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

fooz
  • Members
  • 8 posts
  • Last active: Feb 23 2006 09:03 AM
  • Joined: 08 Jan 2006
Ok. I got method 1 to work, but I'd still like to learn more about how CMDret works. The first method is acceptable because my passed value can be an integer, but in the future it would help to have the flexibility to pass floats and strings and multiple values.

Regarding CMDret, and the following code:

CMDout=
CMDerr=
ProgramName := "C:\php\php.exe getVPIP.php 5"

Ret := RunWaitEx(ProgramName, NULL, TextIn, CMDout, CMDerr)
MsgBox, Return Value: %Ret% `r`n`r`nStdError: `r`n%CMDerr%`r`nStdOutput: `r`n%CMDout%

RunWaitEx(CMD, CMDdir, CMDin, ByRef CMDout, ByRef CMDerr)
{
VarSetCapacity(CMDOut, 100000)
VarSetCapacity(CMDerr, 100000)
RetVal := DllCall("cmdret.dll\RunWEx", "str", CMD, "str", CMDdir, "str", CMDin, "str", CMDout, "str", CMDerr)
Return, %RetVal%
} 

I am using it to call a PHP program that outputs values/data to standard out. Is this what is captured in "CMDout"? Or do I need to somehow access that variable by reference within the called PHP program?



The way I got method 1 to work was by:
- ensuring the PHP program was passing specifically an INTEGER in its exit code
- and, using the full path to reference both the php.exe and the .php file

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004

I am using it to call a PHP program that outputs values/data to standard out. Is this what is captured in "CMDout"? Or do I need to somehow access that variable by reference within the called PHP program?

CMDout should contain the text that was output to standard out :) .

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Although CmdRet is a fine tool, I never needed it. I use one of a few very simple approaches:
- I start "cmd.exe /c" with console programs, which accept a parameter, an expression to be evaluated, and redirect the output to a file. This file is read back by the AHK script. Because the file remains in the Windows buffer, this is not slower than any other method. Here is an example, which evaluates the marked expression and writes the result back to the same application.
!x::
   Send ^x
   calc = %ClipBoard%
   StringReplace calc, calc, ^, ^^, All
   StringReplace calc, calc, <, ^<, All
   StringReplace calc, calc, >, ^>, All
   RunWait %Comspec% /c "C:\Program Files\GnuWin32\bin\calc.exe" -p %calc% > c:\calc.tmp,,HIDE
   FileRead Result, c:\calc.tmp
   StringTrimRight Result, Result, 2
   StringReplace Result, Result, `r`n, `;, All
   Send ^v = %Result%
Return
- There are console programs, like LUA, which take input from a file. Cmd.exe allows writing the result to another file. The input file can be set up in AHK, and the result is read and processed in AHK.
AHKvar = 14

FileDelete C:\LUA.IN
FileAppend,
(
   c = 1+2*3-%AHKvar%
   print(c)
)
, C:\LUA.IN
RunWait %COMSPEC% /c C:\LUA\bin\lua.exe C:\LUA.IN > C:\LUA.OUT,,HIDE
FileRead result, C:\LUA.OUT
MsgBox %result%
- If a console application does not take input from a file, you can still use cmd.exe with "< file.in".
- If an application needs to start up and waits for the input, we can use Send from a Timer subroutine to give it its input. This example runs the Diehard randomness test with some parameters, and the result is processed in an editor, moving the cursor to the first failed result.
SetTimer Keys
RunWait %DieHard%\DIEHARD.EXE, %DieHard%,,PID
Run C:\t\notepad2\Notepad2.exe %DieHard%\%file%.res,,,np2PID
WinActivate ahk_pid %np2PID%
WinWaitActive ahk_pid %np2PID%
ControlSend,,{F3},ahk_pid %np2PID%
Sleep 250
ControlSend,Edit1,.0000{Enter},ahk_pid %np2PID%
Return

Keys:
   IfWinNotExist ahk_pid %PID%
      Return
   SetTimer Keys, Off
   ControlSend,,%file%.dat{Enter},ahk_pid %PID%
   ControlSend,,%file%.res{Enter},ahk_pid %PID%
   ControlSend,,111111111111111{Enter},ahk_pid %PID%
Return
- If a console application does not allow redirecting the output, you can always use the Clipboard to get the content of the terminal window. It is the case with interactive programs, where you want to see the output and also capture it.

fooz
  • Members
  • 8 posts
  • Last active: Feb 23 2006 09:03 AM
  • Joined: 08 Jan 2006
Both the file and clipboard methods seem sloppy to me.

The php file I'm calling is a database api that I run many times a second to pull information from the database. Using file i/o would certainly slow this process down. And as for the clipboard, what if I'm copying and pasting in another app, couldn't I potentially lose either the programs data or the manual data I'm copying and pasting?

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005

Both the file and clipboard methods seem sloppy to me.

Several months ago we benchmarked all the return value capture methods we could think of (including modifications of the program to be run):
- ErrorLevel as return value
- Exit code
- Clipboard
- Process memory access (dll)
- Registry I/O
- Temporary files
- CmdRet dll
The temporary file method in the root directory of the boot disk was the fastest, for the reasons I mentioned: the file is created in the Windows buffer and accessed from there (delayed write). If it is deleted in the script, it never gets written to the disk, so it is just accessing fast internal memory. An idle disk is not even spun up.

Accessing a dll is not fast, even if it is cached. Also, it requires to install an extra file in all the machines your script is run, and update that, too, when the OS or the compiled script changes.

...as for the clipboard, what if I'm copying and pasting in another app, couldn't I potentially lose either the programs data or the manual data I'm copying and pasting?

You could save the clipboard content to an AHK variable before using the clipboard, and restore it at the end. I don't normally do it, because it could be slow if you have a gigabyte clipboard. Instead I use my own clipboard management script, which saves automatically, what I need.

fooz
  • Members
  • 8 posts
  • Last active: Feb 23 2006 09:03 AM
  • Joined: 08 Jan 2006
Great to hear about the file i/o benchmarking results. Thanks!

shimanov
  • Members
  • 610 posts
  • Last active: Jul 18 2006 08:35 PM
  • Joined: 25 Sep 2005

Accessing a dll is not fast, even if it is cached.


Accessing a DLL file loaded in memory is fast, which is the case for many of the core libraries.

Also, it requires to install an extra file in all the machines your script is run, and update that, too, when the OS or the compiled script changes.


Given a careful selection of functions (easily accomplished), the library file(s) will exist on all Windows platforms and this will not be an issue.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005

Accessing a DLL file loaded in memory is fast, which is the case for many of the core libraries.

The benchmarks showed, that dll calls are not faster than buffered disk I/O, that is, dll calls accessing different processes or windows are slow.

Given a careful selection of functions (easily accomplished), the library file(s) will exist on all Windows platforms and this will not be an issue.

We are speaking about CmdRet, a custom dll to capture the standard output in an AHK variable.