 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10463
|
Posted: Tue May 24, 2005 2:04 pm Post subject: |
|
|
| corrupt wrote: | Updated to version 3.1.1
- Added another function to the dll (RunReturn) to allow returning output to a variable. |
This is nicely compact. Your continuing improvements are making this irresistible
Eventually, a syntax will be devised to have CmdRet as a built-in feature: either a direct extension of the Run command or a separate helper command. Perhaps simply adding an OutputVar parameter to the end of the Run command is workable.
Thanks. |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Tue May 24, 2005 6:58 pm Post subject: Very nice! |
|
|
Great stuff, corrupt!!
Until Chris made the following comment in a different thread, ...
| Quote: | | By the way, if you have the DLL copy its result into a string provided by the caller, you can avoid the need for LoadLibrary(), FreeLibrary() and lstrcpy(). |
... the fact that DllCall makes it possible for a DLL to modify the contents of an AHK variable had somehow eluded me (despite the fact that it's clearly stated in the docs! ). Once it finally hit me yesterday, I realized I am now be in a position to actually contribute code to this community (remember I'm the C/Assembler guy who can't do C++), so until your latest release, I had starting planning something along the lines of
| Code: | @ := "str" ; For readability
ExitCode := DllCall("AHKEx\RunWaitEx", @, "executable", @, "parameters", @, "workingdir", @, InVar, @, OutVar, @, ErrVar, "int") |
for quietly launching console programs with fully redirected I/O (unlike AHK's RunWait, I was thinking of separating the executable from its parameters in order to avoid having to reproduce AHK's no-doubt complicated parsing rules for figuring out where one ends and the other begins). InVar above could be replaced by an explicit string, but OutVar and ErrVar would be appropriately sized variables. The programmer would initially assume the risk of insufficiently sized output variables, unless I can come up with a simple way to pass the current size of a variable to the call without burdening the syntax with additional parameters, like maybe making the initial contents of a variable reflect its size?
| Code: | VarSetCapacity(OutVar, 10240)
OutVar = 10240 |
(Hmm, I wonder whether I can talk Chris into a VarSetCapacity option to place the variable's new size as a DWORD in its first 4 bytes? Would save the conversion work...)
In any case, now that you've made such progress with CmdRet, I'd like to put the question whether I should proceed (when time allows) or whether you might be planning a similar more complete implementation of your new RunReturn call? [BTW, may I ask in what language you wrote CmdRet.dll? I was surprised by its tiny size, almost Assembler-like!)
Again, congratulations on a job well done!
Jacques. |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Tue May 24, 2005 7:49 pm Post subject: Question for Chris |
|
|
Chris,
Based on the various discussions of DllCall that have sprung up since you released the feature [with due credit of course to Marcus Sonntag (Ultra)] and thinking now about using it to add AHK capabilities without bugging you for every little thing, can I assume that the internal format of an AHK variable is a straight null-terminated string (within a pre-allocated buffer the size of which you keep track of separately and expand as needed?) I guess what I'm trying to confirm is that AHK variables don't have some sort of "header" structure containing their size, type, etc., as is sometimes the case in the implementation of other interpreted languages (anybody out there still remember my all-time favorite language, APL?)
[Bonus question, for pure curiosity: if that is in fact the case (variables = null-terminated strings), how were you planning to implement the reading/writing of binary files which I think I've seen you mention as a future possibility?]
Jacques. |
|
| Back to top |
|
 |
Guest
|
Posted: Tue May 24, 2005 9:19 pm Post subject: |
|
|
| Jacques wrote: | Great stuff, corrupt!!
Until Chris made the following comment in a different thread, ...
| Quote: |
By the way, if you have the DLL copy its result into a string provided by the caller, you can avoid the need for LoadLibrary(), FreeLibrary() and lstrcpy(). |
|
Thanks:)
The latest version of CMDret (3.11) does copy the result back into a variable provided by the caller (RunReturn function) .
CMDret has been designed using BCX.
corrupt |
|
| Back to top |
|
 |
Guest
|
Posted: Tue May 24, 2005 9:23 pm Post subject: |
|
|
| Chris wrote: | | corrupt wrote: | Updated to version 3.1.1
- Added another function to the dll (RunReturn) to allow returning output to a variable. |
This is nicely compact. Your continuing improvements are making this irresistible  |
Thanks
corrupt |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Tue May 24, 2005 10:01 pm Post subject: |
|
|
| corrupt wrote: | | The latest version of CMDret (3.11) does copy the result back into a variable provided by the caller (RunReturn function) |
Yes, that's the version I was congratulating you about! The functions in the previous versions were certainly very nice (e.g. RunRedirect), but their syntax wasn't sufficiently streamlined to provide a "clean" alternative to RunWait.
Jacques. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10463
|
Posted: Wed May 25, 2005 1:32 am Post subject: Re: Question for Chris |
|
|
| JBensimon wrote: | | a VarSetCapacity option to place the variable's new size as a DWORD in its first 4 bytes? Would save the conversion work...) | I see that it would be useful, but the uses seem too obscure to justify cluttering the command with such an option. If after more thought you're convinced that the value would be substantial and have a broad range of applications, please let me know.
| Quote: | | can I assume that the internal format of an AHK variable is a straight null-terminated string (within a pre-allocated buffer the size of which you keep track of separately and expand as needed?) | Yes. When you pass a variable by reference to a function (by means of a "str" argument type), the address of the variable's null-terminated buffer gets passed to the function. It's the function's responsibility (if it changes the string) to terminate the buffer and not to exceed the buffer size. After the function completes, the program updates the variable's length attribute in case the function changed the string.
| Quote: | | I guess what I'm trying to confirm is that AHK variables don't have some sort of "header" structure containing their size, type, etc. | They do, but this info is not passed to the function, only the buffer is.
| Quote: | | how were you planning to implement the reading/writing of binary files which I think I've seen you mention as a future possibility? | I'm not sure yet but it might expand on the special ClipboardAll variable, whose contents can be stored in ordinary variables as binary data. Also, it is already possible to read and write binary files using the example in this post: http://www.autohotkey.com/forum/viewtopic.php?p=22389#22389 |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Wed May 25, 2005 2:16 am Post subject: |
|
|
| Chris wrote: | | If after more thought you're convinced that the value would be substantial and have a broad range of applications... |
Probably not. If you think scripts should make no assumption about the contents of a variable after VarSetCapacity has been applied to it, then you might consider my suggestion as a default behavior. If on the other hand a variable's value should be expected to be an empty string after VarSetCapacity has been applied, then please ignore the suggestion.
| Chris wrote: | | Also, it is already possible to read and write binary files using the example in this post ... |
Thanks, I'll check it out ... but I'm probably sticking to text files for now.
Jacques. |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2381
|
Posted: Wed May 25, 2005 6:52 am Post subject: Re: Very nice! |
|
|
| JBensimon wrote: | | In any case, now that you've made such progress with CmdRet, I'd like to put the question whether I should proceed (when time allows) or whether you might be planning a similar more complete implementation of your new RunReturn call? |
| JBensimon wrote: | @ := "str" ; For readability
ExitCode := DllCall("AHKEx\RunWaitEx", @, "executable", @, "parameters", @, "workingdir", @, InVar, @, OutVar, @, ErrVar, "int") |
A similar, more complete function could be implemented in the near future. With version 3.1.1 I was trying to simplify (and reduce the amount of) the code necessary to call the function. I am also planning to release the source for CMDret soon (BCX, C). You're welcome to write your own if you'd like though .
Could you give an example that would use InVar?
Thanks Again  |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2381
|
Posted: Wed May 25, 2005 7:06 am Post subject: |
|
|
| Chris wrote: | | Eventually, a syntax will be devised to have CmdRet as a built-in feature: either a direct extension of the Run command or a separate helper command. Perhaps simply adding an OutputVar parameter to the end of the Run command is workable. | Adding an OutputVar parameter to the end of RunWait sounds workable. Any thoughts on syntax to stream into a control? |
|
| Back to top |
|
 |
jonny
Joined: 13 Nov 2004 Posts: 3005 Location: Minnesota
|
Posted: Wed May 25, 2005 1:52 pm Post subject: |
|
|
My two monetary units of low value:
Since most utilities that this would used for would, in theory, return a value, and since that value is often only needed once, I think this would be a good opportunity to implement a RunWait function. This would also make the syntax for assigning output to a variable more readable:
cmdOutput:=RunWait("tail.exe test.txt") |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10463
|
Posted: Wed May 25, 2005 10:37 pm Post subject: |
|
|
| JBensimon wrote: | | If on the other hand a variable's value should be expected to be an empty string after VarSetCapacity has been applied, then please ignore the suggestion. | I think it's best that the variable be empty after the change (which it currently is). This allows the script to pass a string that is known to be empty and initialized, which at the very least adds peace of mind, and in some cases saves the extra step of having to make the variable blank. Now that I think about it, it's fortunate that the variable is made blank because manually setting it to blank afterward would free the memory you just allocated!
| Quote: | | Any thoughts on syntax to stream into a control? | I haven't been paying enough attention to cmdret. I'll assume it has stream-to-control capability and I've made a note to consider how the syntax might work for that. Hopefully this can be an entirely separate task so that the integration into Run/RunWait isn't postponed by it. Thanks. |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Thu May 26, 2005 12:33 am Post subject: |
|
|
| jonny wrote: | Since most utilities [...] return a value [...]
| Code: | | cmdOutput:=RunWait("tail.exe test.txt") |
|
Your suggestion is certainly compact, but I think the intuitive "result" of a console utility is its exit code, not its console output (because you often need to check the exit code before you can interpret the meaning of the output), as in
| Code: | If (RunWait("command", OutVar)=0)
MsgBox, 0, Output, %OutVar%
Else
MsgBox, 48, Failure, An error was encountered. |
Then there's the question of being able to set the working directory (often very important), of being able to distinguish between normal and error output (well designed console utilities make a careful distinction between the two output handles), of providing for the ability to also provide the utility's standard input (e.g. sort.exe, findstr.exe, etc.), and pretty soon we're back to a function (or AHK command) with multiple parameters. [I'm assuming here that we don't need to offer the usual Min, Max & Hide choices since we probably always want to hide the launched utility when we're trying to capture its output in a variable].
From the standpoint of readability, given than console utilities often take arguments that may require double-quotes (e.g. filenames), an extended version of the RunWait command seems "cleaner" than a new function. As we've been discussing recently, it would then be a simple matter for any AHK programmer who wants it to define a custom RunWait-like function that "wraps" the RunWait command, takes just the needed parameter(s), and returns exactly what the programmer wishes.
Just giving back some change on those two cents!
Jacques. |
|
| Back to top |
|
 |
JBensimon
Joined: 16 Nov 2004 Posts: 130 Location: New York
|
Posted: Thu May 26, 2005 3:14 am Post subject: Re: Very nice! |
|
|
| corrupt wrote: | | Could you give an example that would use InVar? |
Happy to! Almost any so-called "filter" utility (a console utility that takes input from StdIn and sends output to StdOut) is a candidate. There are hundreds of filters in the scripting arsenal of Unix programmers (most of which have been ported to Windows by somebody or other), and many non-trivial tasks can be carried out by stringing together several filters, each one taking its input from the output of the previous one. You are probably already familiar with many simple filters, among which are more, head, tail, sort, find, grep, gsar (GNU Search And Replace), etc. One of the more useful filters found in all versions of Windows starting with NT is FindStr.exe, a much more powerful alternative to Find.exe because of its support for regular expressions (i.e. pattern matching).
So, just as a simple example, let's say you have an AHK variable called Requests, a line-feed separated list of strings typed by a user, and you only want to proces the strings in which the user said "please", i.e. strings in which the word "please" appears anywhere (the words "pleased" or "displease" would not be acceptable). In the hypothetical scenario where RunWait accepts new InVar and OutVar parameters, you could use the command
| Code: | | RunWait, FindStr.exe /i "\<please\>",, Hide,, Requests, PoliteRequests |
and the PoliteRequests variable would now contain only those strings that contain the word "please" (case-insensitive).
Jacques. |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2381
|
Posted: Sat May 28, 2005 6:37 pm Post subject: |
|
|
It seems that the download link is currently down for a few people so here's an Alternate Download . |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|