new messages for TC scripting/ More Automation possibilities

Here you can propose new features, make suggestions etc.

Moderators: Hacker, petermad, Stefan2, white

User avatar
nsp
Power Member
Power Member
Posts: 1913
Joined: 2005-12-04, 08:39 UTC
Location: Lyon (FRANCE)
Contact:

new messages for TC scripting/ More Automation possibilities

Post by *nsp »

It could be nice to have some windows message like CD,VP,EM .. with copydata that do :
A) what do command bar !
=> ability to send wfx specific command
=> launch program as TC child
...
B) Add operation to TC Queue
ex QE or Q\0E copy\rc:\test\F1\r%TEMP%

C) Messages that return current files %F or %P%S or %M

D) Message tat return current paths (%P, %T)


A official doc of all accepted messages !


It could also be nice to have %P %N %S %F %L ... supported in command bar and also with all copydata messages )

-- -- Edited -- Subject completion
Last edited by nsp on 2010-12-11, 05:38 UTC, edited 1 time in total.
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

=> launch program as TC child
This may be used by viruses:)
User avatar
nsp
Power Member
Power Member
Posts: 1913
Joined: 2005-12-04, 08:39 UTC
Location: Lyon (FRANCE)
Contact:

Post by *nsp »

MVV wrote:
=> launch program as TC child
This may be used by viruses:)
Does vpbatch become a virus using <add and <exec ;)

correct => launch program as TC does.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

I have an Autohotkey Library that that can send "CD" and "EM" or "CM" by name.

My AHK CD command also optionally selects a filename if it is given a fullpath\filename instead of just a path.

Also I wrote a ListBox Library that can return the list of selected items in a TC panel. The only problem atm is for some reason it doesn't work for Thumbnail view, but it does for all others: Details, Brief, Comments or Custom Columns. I had planned to ask Christian what is different about the Thumbnail mode's ListBox.

The only semi-quirk with the ListBox Library is with TC's Details (mode) file listing, TC doesn't delimit the filename before the size field, unlike with a custom column (or Comments) that will always place a ">" character after the filename. Thus you need to use a small regex to grab the filename. It would be great if the ">" was included in Details mode though. I'm not sure if that request would go unheeded though. I'm usually not successful in non-bug related post/requests.

Eg, a Listbox test of "selected files", Details mode:

Code: Select all

_LBTest.ahk
---------------------------
Selection Result:
---------------------------
|_LBTest.ahk 2 k 11/28/10 12:37 -a--|
|_ODoc.ahk 11 k 12/06/10 16:53 -a--|
|_OTEST.ahk 1 k 12/08/10 01:47 -a--|
|_ST2A.ahk 13 k 12/06/10 14:14 -a--|
Comments View:

Code: Select all

_LBTest.ahk
---------------------------
Selection Result:
---------------------------
|_LBTest.ahk > |
|_ODoc.ahk > |
|_OTEST.ahk > |
|_ST2A.ahk > |
Custom Column:

Code: Select all

_LBTest.ahk
---------------------------
Selection Result:
---------------------------
|_LBTest.ahk >2 k x  .|
|_ODoc.ahk >11 k x  .|
|_OTEST.ahk >1 k x  .|
|_ST2A.ahk >13 k x  .|
Brief Mode:

Code: Select all

_LBTest.ahk
---------------------------
Selection Result:
---------------------------
|_LBTest.ahk|
|_ODoc.ahk|
|_OTEST.ahk|
|_ST2A.ahk|
Thumbnail View: Not able to return / read anything at all.
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

Though honestly, I think TC is long overdue for internal scripting. It is available now in many other File Managers, like FileBoss or xyplorer.

Lately when I do tasks with AHK it at times feels like a hack or workaround as opposed to just extending TC. If there was a better way to interface from a script it would be very appreciated, even if internal scripting wasn't added.

So yes, I do agree it would be good to be able to Query a list of selected files. Getting the current path is generally pretty easy though.
As opposed to the current route, forcing TC to copy the files to clipboard. My ListBox library works, but I haven't 100% tested, and I'm not happy with the regex filter for details mode yet either.

Even my editor of choice (EmEditor) has complete support for scripting, VBscript or JavaScript -- with full access to all internal commands and variables as needed.
MVV wrote:
=> launch program as TC child
This may be used by viruses:)
That shouldn't even be a consideration. You can already set the text inside TC's command prompt and force an action from there, eg launching a cmd.exe. But why bother with forcing TC to launch a program if a virus is embedded into your system already it will hardly need TC to run wild.
Or inject text into TC's .ini files to create a new em_command that can launch a file directly.
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50475
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Why do you think that each program on Windows needs its own scripting? Windows is a multitasking system, so it's better to have one scripting tool for various tasks. Otherwise you have to learn a new language for every program, and sceipting involving multiple programs isn't possible either. For example, I'm using AutoHotkey myself to create mail replies, attach keys, store received orders to files etc. which wouldn't be possible with a scripting tool limited to one program.
Author of Total Commander
https://www.ghisler.com
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

An internal scripting program would have direct access to internal variables like, %S.
It would be able to query the list of selected files without sending a command to TC to cause it to paste into the Clipboard -- or without parsing the ListBox which returns whole lines that aren't "tab", or "newline" delimited to split up the columns. Whereas when TC copies file details to the Clipboard, the columns of the FilePanels are hard-Tab delimited.

An internal scripting program could call cm_commands without looping through the totalcmd.inc file to match names with numbers.

An internal scripting program would be able to know what the current %COMMANDER_INI% value is, without hackish workarounds.

Now if those things were possible, the "desire" for an internal script wouldn't be so prevalent. Off the top of my head anyways.

1) And as I indicated, minimally, it would be nice for the
DetailsMode "text" that is returned when querying TC's Panel listbox be delimited by a ">" after the filename like all the other Column types are.

2) As well, a CM_Command's that would return the current %COMMANDER_INI% and COMMANDER_PATH values. They are retrievable thru hacks only - to an outside script that hasn't been launched from TC.

3) And as NSP indicated, a clean way to query the Target and Source paths.

Note: The problem with calling a script from TC, and then passing it a list of files with %S --- if too many files are selected the whole command will fail due to a total message size limitation in how it is passed.
Whereas if the column values were ">" delimited or "TAB" delimited (like they are when the CopyFileDetailsToClip command is used. Then one could just query standard windows ListBox commands and easily be able to determine what the file is and even what the values of the other columns are.

Also, as far as I can tell. The TABS aren't queryable for the text name. Apparently TabBoxes are protected from outside processes from even reading them.
so:
4) A way to query the current active Tab name, without resorting to parsing the wincmd.ini file and matching the TabBox number with a possible value in the wincmd.ini.
-- I am able to get the tab-index, and current Tab number. Just cannot get what the Tab has been named.

Anyways, that's my 0.04cents ;)
User avatar
JohnFredC
Power Member
Power Member
Posts: 886
Joined: 2003-03-14, 13:37 UTC
Location: Sarasota Florida

Post by *JohnFredC »

One thing I have learned over the years about internal scripting is that, with the right architecture, an internal script model reduces programmer effort.

Here is a little story... please bear with me?
  • When first I started selling group automation software written in MS Access (VB) I followed the programming model learned in school: using the RAD for the entire GUI and hard coding the links to every single function/procedure. The only "soft" components were tables of user data manipulated with SQL.

    After a while I realized that the same powerful tools employed for user data (tables, queries, etc) could be used indirectly to define the UI. So in the next phase I moved the UI into hidden "system tables". The advantage to that was that the UI could be defined via values in table fields plus SQL code to create the control display list appropriate for nearly every form and dialog needed. This considerably lowered the manual effort required to create new UIs for new customers.

    After a couple of years it occurred to me that the same metaphor (tables of data controlled by SQL) could be used to build the functionality of the applications as well. I hard coded a large number of "atomic" functions, listed them (plus a variety of externally editable attributes) in a function table, then built all (well most) of the next set of apps by creating execution lists in a master "application behavior" table and running the SQL performance loop against it.

    At that point, something like 75% of an application could be defined solely by editing the UI table, the function table, and the behavior table... much less time spent in the Access RAD. For a couple of customers I even exposed a little interface where they could build batch scripts "by example"... no coding, just adding functions as sequential records in an execution table (though the UI didn't look like that). They loved it.

    Obviously the (IMO) brilliant design of the Access development architecture (the melding of SQL with VB and the GUI runtime environment) enabled my efforts.
But my point isn't about Access, or SQL, or tables...

My point is: If one's thinking starts at what eventually became my end-point (user "scripting") and works backward toward an application's core, at some point it will be come apparent that the developer can use the scripting capability himself to leverage the development effort and increase programming productivity. Bootstrapping the app, as it were.

For example, a frequent past request in the TC forums has been that a single TC button click could iterate through all selected files and perform some function on each one. Well, obviously a script with a loop is an good candidate for that! If TC was driven internally by a scripting paradigm...

Well, hopefully I have made my point. Support for scripting can benefit both users and developers!

An excellent example of this approach to application architecture is MOI3D. Download/install the demo, then browse the files in the "Commands" subfolder... almost the entire application is "soft"...

A pfennig's worth, perhaps?
Licensed, Mouse-Centric, moving (slowly) toward Touch-centric
User avatar
nsp
Power Member
Power Member
Posts: 1913
Joined: 2005-12-04, 08:39 UTC
Location: Lyon (FRANCE)
Contact:

More automation possibilities for TC.

Post by *nsp »

ghisler(Author) wrote:Why do you think that each program on Windows needs its own scripting? Windows is a multitasking system, so it's better to have one scripting tool for various tasks. Otherwise you have to learn a new language for every program, and sceipting involving multiple programs isn't possible either. For example, I'm using AutoHotkey myself to create mail replies, attach keys, store received orders to files etc. which wouldn't be possible with a scripting tool limited to one program.
Dear M. Ghisler,

Read carefully the suggestion, it is not about embedding internal scripting to TC.
The suggestion is to have :
1 - More messaging support with TC.
* Get some info from TC.
* Complete a little current WM_copydata message EM, CD, VP , ??.
* ability to interact a little more with TC (like ability to add to copy/move queue )

2 - an official document that list all accepted message.


I do not ask for internal scripting !

I called scripting by mistake let's rename it to more automation possibilities for TC
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

I also apologize if I derailed the thread at all.
I was only pointing out how/why internal script is usually better than external. And pined that internal scripting would be superfantasticallyastic ;-)

Please bear in mind as well, my suggestions along with nsp's on current issues with interfacing with TC from external scripts, that could be improved upon. And would be most welcome.

Most decent scripting tools, can "SendMessage" and wait for a response. If TC had cm_Commands for querying:
  1. Current SourcePath
  2. Current TargetPath
  3. Which Panel is active, possible return values, "1", "R", "2", "L"
  4. What the current Tab is named.
  5. hard-tab delimits in the ListBoxes (Like the CopyFileDetailsToClip command):
    --- When Windows ListBox API's are used, can consistently get the filename (or other TabStop fields).
    --- Or minimally just add a ">" after the filename for Details View: like CustomColumns & Comments View.
NOTES 1-3:
These are all possible already, if you are well versed in your scripting tool of choice. But would be cleaner and easier for new Scripter's if they were queryable SendMessage cm_Commands.
And to accurately get the target path, you need to go through multiple steps:
1) Find the panel that is not active
- Not possible if one of TC's dialogs are currently active.
2) Query the text inside TPathPanel
3) Run a regex to remove text that might be a "display filter"
NOTES 4-5: Are not consistently possible at all.
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

- Not possible if one of TC's dialogs are currently active.
Should be possible using SendMessage and Autorun_HideMenu (download link in this post). :) It remembers last focused child of main TC window when it loses focus and allows to determine active panel. But of course internal solution would be perfect.
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50475
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

If TC had cm_Commands for querying:
1. Current SourcePath
2. Current TargetPath
That would indeed be nice, but how can it be done? WM_COPYDATA only allows to send data, not return any. The only return value is a number when using SendMessage:
http://msdn.microsoft.com/en-us/library/ms649011%28v=vs.85%29.aspx
The receiving application should consider the data read-only.
Author of Total Commander
https://www.ghisler.com
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

The code below is from the AHK Helpfile, on how to send Messages between scripts, acknowledge the message (return 1)
=====================================
Similar to how we can send the "CD" "EM" "CM" Messages to TC (I currently use WM_COPYDATA for CD/EM/CM - though after a discussion w/ nsp, there may be parts of the code that need to be made unicode-friendly).

Basically, reserve ~100 numbers in the free cm_command space for "Query" messages. I believe the range 6001 - 20000 is empty currently. E.g.
9900: QuerySourcePath
9901: QueryTargetPath
...
9999: QueryCommanderINI
etc.
Example:
SendMessage, 0x433, 9901, %ScriptsHWND%,,ahk_id %TCsHWND%
TC responds with a WM_COPYDATA message to the calling scripts HWND, and the calling script processes the lParam (the "string" response to the query) of the WM_COPYDATA message. In AHK that would be done with "OnMessage()".

Something like the code below could be used to process the message from TC. It's lower-level code as far as scripting is concerned, but the concept is sound -- If there were a defined set of messages TC would respond to.

Code: Select all

; Example: Send a string of any length from one script to another.  This is a working example.
; To use it, save and run both of the following scripts then press Win+Space to show an
; InputBox that will prompt you to type in a string.
; Save the following script as "Receiver.ahk" then launch it:
#SingleInstance
OnMessage(0x4a, "Receive_WM_COPYDATA")  ; 0x4a is WM_COPYDATA
return
Receive_WM_COPYDATA(wParam, lParam)
{
    StringAddress := NumGet(lParam + 8)  ; lParam+8 is the address of CopyDataStruct's lpData member.
    StringLength := DllCall("lstrlen", UInt, StringAddress)
    if StringLength <= 0
        ToolTip %A_ScriptName%`nA blank string was received or there was an error.
    else
    {
        VarSetCapacity(CopyOfData, StringLength)
        DllCall("lstrcpy", "str", CopyOfData, "uint", StringAddress)  ; Copy the string out of the structure.
        ; Show it with ToolTip vs. MsgBox so we can return in a timely fashion:
        ToolTip %A_ScriptName%`nReceived the following string:`n%CopyOfData%
    }
    return true  ; Returning 1 (true) is the traditional way to acknowledge this message.
}

Code: Select all

;;
;; --- Balderstrom NOTE--- 
;; This part would not be needed by the script. 
;; As TC would be the Sender to the Script. 
;;
; Save the following script as "Sender.ahk" then launch it.  After that, press the Win+Space hotkey.
TargetScriptTitle = Receiver.ahk ahk_class AutoHotkey
#space::  ; Win+Space hotkey. Press it to show an InputBox for entry of a message string.
InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send:
if ErrorLevel  ; User pressed the Cancel button.
    return
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if result = FAIL
    MsgBox SendMessage failed. Does the following WinTitle exist?:`n%TargetScriptTitle%
else if result = 0
    MsgBox Message sent but the target window responded with 0, which may mean it ignored it.
return
Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  ; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.
{
    VarSetCapacity(CopyDataStruct, 12, 0)  ; Set up the structure's memory area.
    ; First set the structure's cbData member to the size of the string, including its zero terminator:
    NumPut(StrLen(StringToSend) + 1, CopyDataStruct, 4)  ; OS requires that this be done.
    NumPut(&StringToSend, CopyDataStruct, 8)  ; Set lpData to point to the string itself.
    Prev_DetectHiddenWindows := A_DetectHiddenWindows
    Prev_TitleMatchMode := A_TitleMatchMode
    DetectHiddenWindows On
    SetTitleMatchMode 2
    SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle%  ; 0x4a is WM_COPYDATA. Must use Send not Post.
    DetectHiddenWindows %Prev_DetectHiddenWindows%  ; Restore original setting for the caller.
    SetTitleMatchMode %Prev_TitleMatchMode%         ; Same.
    return ErrorLevel  ; Return SendMessage's reply back to our caller.
}
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50475
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Interesting, that's what I'm doing with Irfanview (and Xnview) too: Send name of image to it via WM_COPYDATA, receive bitmap data also via WM_COPYDATA. I just didn't expect that AHK actually has a window and can receive messages...
Author of Total Commander
https://www.ghisler.com
User avatar
ZoSTeR
Power Member
Power Member
Posts: 1049
Joined: 2004-07-29, 11:00 UTC

Post by *ZoSTeR »

That would also work in AutoIt with something like this:

Code: Select all

GUIRegisterMsg($WM_COPYDATA, "WM_COPYDATA_ReceiveData")

Func WM_COPYDATA_ReceiveData($hWnd, $MsgID, $wParam, $lParam) ;
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr", $lParam)
    Local $tMsg = DllStructCreate("char[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3))
    $received = DllStructGetData($tMsg, 1)
EndFunc
Post Reply