Call Methods from ActiveX (COM) Objects from the TCC CLI

#1
This is by no means a finished batch file, but it is a start to a solution in which I can access COM Objects from the TCC CLI. Source code for COMCALL.BTM is below the Q&A.

Questions with Answers
Q. Where exactly can I get these "COM Objects" to install on my system?

A. Your system already has quite a few COM Objects on it.
To display a complete list of Registered Objects on your Windows System, refer to this forum message;
[title]

Q. Okay, I've got a list of the Registered Objects that are on my system. How do I find out the methods for a specific COM Object?

A. To list the methods for an ActiveX (COM) Object, refer to this forum message;
[title]

Q. How about an example of what COMCALL.BTM can do?

A. Let's say that you wanted to do something similar as the TCC @GETFOLDER Function does.

Code:
comcall shell.application "Folder BrowseForFolder (int, string, int, Variant)" 0, "Example", 0, "36"
Q. Where did you get that "Folder BrowseForFolder (int, string, int, Variant)" line, and what is it for?

A. I used methodlist.btm as follows;

Code:
methodlist.btm shell.application
A list of the methods was returned. Using my mouse, I copied the definition for BrowseForFolder to the clipboard, and pasted it into the command line.

Q. Why do I need "Folder BrowseForFolder (int, string, int, Variant)"?

A. It allows the batch file to determine the name of the method, and the number and type of arguments for the method.

Q. Why do you need to use CScript.exe with this batch file?

A. TCC does not have the ability to call COM Objects, but CScript.exe does.

Q. Why do you need to use PowerShell.exe with COMLIST.BTM and METHODLIST.BTM?

A. TCC does not have the ability to call COM Objects, but PowerShell.exe does.

Q. Why did you not just use CScript.exe with COMLIST.BTM and METHODLIST.BTM?

A. The only way I could figure out how to do the same thing with CScript.exe would have required each system to have the TLBINF32.dll file installed on everyone's system.

TLBINF32.dll came with my copy of Visual Sudio 6.0, and I cannot find if it is legal to distribute it.

I hope that others find this batch file useful. For me, I can now call from the TCC CLI all of the functions in the Visual Basic 6.0 COM Objects that I created over the years. I have been calling my COM Objects from VBScript, PowerShell, AutoIt, PowerBASIC, and now, I can call them from TCC, without having to re-create the functions in TCC.

Joe

Code:
::--------------------------------------------------------------------
:: comcall.BTM
::
:: Call Methods from ActiveX (COM) Objects from the CLI
::
:: TCC 15.01.52
:: 2013/08/05
:: Joe Caverly
::
:: I am working on a TCC Plugin to accomplish this same task, and am
::   using this as an example of what I want to accomplish.
::
:: The plugin version will be a function (@comcall)
::   and a command (comcall).
::
:: This batch file requires cscript.exe in order to work properly.
::
:: TODO: Error checking of command line arguments, misc. stuff.
::       Error checking in the .vbs script that this batch file creates.
::--------------------------------------------------------------------
@setlocal
@echo off

:: For     debugging purposes, verbose=1
:: For non-debugging purposes, verbose=0
set verbose=0

set BatchParameters=%#
if %verbose=1 echo Batch Parameters=%BatchParameters

set dispatch=%1
set Definition=%2

iff %BatchParameters lt 2 then
  echo USAGE: comcall dispatch "Definition"
  echo        comcall dispatch "Definition" argument(s)
  echo.
  echo Exple: comcall shell.application "void MinimizeAll ()"
  echo        comcall shell.application "void ControlPanelItem (string)" "desk.cpl"
  echo.
  echo        comcall shell.application "Folder BrowseForFolder (int, string, int, Variant)" 0, "Example", 0, "36"
  echo.
  echo        comcall shell.application "void FileRun ()"
  echo.
  echo        The following calls a COM Object that I created with Visual Basic 6.0;
  echo        comcall jlcutils.clsmath "Variant ppp (Variant)" 6.59
  goto eoj
endiff

if exist %@path[%_batchname]comcall.vbs del %@path[%_batchname]comcall.vbs > nul

::
:: Method return type
::
set MethodReturnType=%@word[0,%@unquote[%Definition]]

::
:: Method name
::
set MethodName=%@word[1,%@unquote[%Definition]]

::
:: How many left parentheses in the "Definition"
::
set LParenthCount=%@count[(,%Definition]
iff %LParenthCount ne 1 then
  echo Error In Definition
  echo %Definition
  goto eoj
else
  if %verbose=1 echo Found 1 left parentheses
endiff

::
:: How many right parentheses in the "Definition"
::
set RParenthCount=%@count[),%Definition]
iff %RParenthCount ne 1 then
  echo Error In Definition
  echo %Definition
  goto eoj
else
  if %verbose=1 echo Found 1 right parentheses
endiff

::
:: Where does the beginning parentheses begin?
::
set BParenth=%@index[%2,(]

::
:: Where does the ending parentheses begin?
::
set EParenth=%@index[%2,)]

::
:: Make sure left is before right parentheses
::
iff %BParenth gt %EParenth then
  echo Definition contains )(, should be ()
  goto eoj
else
  if %verbose=1 echo Definition contains (), okay to continue
endiff

::
:: Get the definition without the parentheses
::
set defLength=%@eval[(%EParenth-%BParenth)-1]
set Definition=%@instr[%@eval[%BParenth+1],%defLength,%Definition]
if %verbose=1 echo Definition without parentheses=%Definition

::
:: How many arguments does the definition have?
::
iff %@eval[%BParenth+1] eq %EParenth then
  set defArgc=0
  if %verbose=1 echo No Arguments
else
  set defArgc=%@words[,%Definition]
  if %verbose=1 echo Definition has %defArgc argument(s)
endiff

::
:: We already know that we have two Batch Parameters,
::   the %dispatch (first) and the %Definition (second)
::   The %defArgc + 2 should equal %BatchParameters
::
if %verbose=1 echo defArgc + 2 = %@eval[%defArgc + 2]
if %verbose=1 echo BatchParameters=%BatchParameters
iff %@eval[%defArgc + 2] le %BatchParameters then
  if %verbose=1 echo Everything is okay to proceed
else
  echo %defArgc arguments are required for the definition (%Definition)
  goto eoj
endiff

switch %defArgc
  case 0
    gosub 0args
  case 1
    set Arg1=%3
    gosub 1args
  case 2
    set Arg1=%3
    set Arg2=%4
    gosub 2args
  case 3
    set Arg1=%3
    set Arg2=%4
    set Arg3=%5
    gosub 3args
  case 4
    set Arg1=%3
    set Arg2=%4
    set Arg3=%5
    set Arg4=%6
    gosub 4args
  default
    echo You have a definition with more than 4 arguments.
    echo Feel free to expand this batch file to accomodate your requirments.
    goto eoj
endswitch

do i = %start to %end
  echo %@line[%_batchname,%i] >> %@path[%_batchname]comcall.vbs
enddo

if %verbose=1 type comcall.vbs

cscript //nologo %@path[%_batchname]comcall.vbs

:eoj
if exist %@path[%_batchname]comcall.vbs del %@path[%_batchname]comcall.vbs > nul
endlocal
quit

:0args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName()
endtext
set end=%@eval[%_batchline-3]
return

:1args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName(%Arg1)
endtext
set end=%@eval[%_batchline-3]
return

:2args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName(%Arg1, %Arg2)
endtext
set end=%@eval[%_batchline-3]
return

:3args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName(%Arg1, %Arg2, %Arg3)
endtext
set end=%@eval[%_batchline-3]
return

:4args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName(%Arg1, %Arg2, %Arg3, %Arg4)
endtext
set end=%@eval[%_batchline-3]
return
 
#2
I have removed the need to copy-and-paste the method definition. The batch file now calls MethodList.btm to get the definition.

You can also create your own Method Definition File, instead of having to call MethodList.btm each time. This makes execution much faster. Read comments in the code for how to do this.

This now requires fewer command-line arguments to enter for the batch file.

Joe

Code:
::--------------------------------------------------------------------
:: comcall.BTM
::
:: Call Methods from ActiveX (COM) Objects from the CLI
::
:: TCC 15.01.52
:: Updated 2013/08/07
:: Joe Caverly
::
:: I am working on a TCC Plugin to accomplish this same task, and am
::  using this as an example of what I want to accomplish.
::
:: The plugin version will be a function (@comcall)
::  and a command (comcall).
::
:: This batch file requires cscript.exe in order to work properly.
::
:: 2013/08/07 - Added ability to get Method Defenition automatically,
::                instead of copying and pasting.
:: 2013/08/07 - Requires MethodList.btm to get Method Definition.
:: 2013/08/07 - Use your own Method Definition File, instead of
::                having to call MethodList.btm each time.
::              Read comments in code for how to do this.
::
:: TODO: Error checking of command line arguments, misc. stuff.
::      Error checking in the .vbs script that this batch file creates.
::--------------------------------------------------------------------
@setlocal
@echo off
 
:: For    debugging purposes, verbose=1
:: For non-debugging purposes, verbose=0
set verbose=0
 
set BatchParameters=%#
if %verbose=1 echo Batch Parameters=%BatchParameters
 
set dispatch=%1
set Method=%2
 
iff %BatchParameters lt 2 then
  echo USAGE: comcall dispatch method
  echo        comcall dispatch method argument(s)
  echo.
  echo Exple: comcall shell.application MinimizeAll
  echo        comcall shell.application ControlPanelItem "desk.cpl"
  echo.
  echo        comcall shell.application BrowseForFolder 0, "Example", 0, "36"
  echo.
  echo        comcall shell.application FileRun
  echo.
  echo        The following calls a COM Object that I created with Visual Basic 6.0;
  echo        comcall jlcutils.clsmath ppp 6.59
  goto eoj
endiff
 
if exist %@path[%_batchname]comcall.tmp del %@path[%_batchname]comcall.tmp > nul
 
::
:: Running METHODLIST.BTM slows things down.
::  You can create your own method definition file to use, by doing, for example;
::
::  methodlist.btm shell.application > c:\mydir\whatever.txt
::
:: Next, before you run this batch file,
::
:: set MethodDefFile=c:\mydir\whatever.txt
::
::  then run this batch file.
::
iff defined MethodDefFile then
  iff exist %MethodDefFile then
    type %MethodDefFile > %@path[%_batchname]comcall.tmp
  else
    echo Cannot find file %MethodDefFile
    echo Batch Job Aborted.
    goto eoj
  endiff
endiff
 
iff exist %@path[%_batchname]comcall.tmp then
  if %verbose=1 echo Using pre-existing method definition file
else
  ::
  :: Call the methodlist.btm to get the method definition
  ::
  which methodlist.btm > nul
  iff %_?  eq 0 then
    call methodlist.btm %dispatch > %@path[%_batchname]comcall.tmp
  else
    echo MethodList.btm is required for this batch file to work.
    echo.
    echo Batch Job Aborted.
    goto eoj
  endiff
endiff
 
set MaxLines=%@lines[%@path[%_batchname]comcall.tmp]
 
::
:: Near the beginning of the comcall.tmp file, there is a header;
::
:: Name                MemberType Definition
:: ----                ---------- ----------
::
:: Look for the word "Definition" in that header.
::
do kount = 1 to %MaxLines
  set theline=%@line[%@path[%_batchname]comcall.tmp,%kount]
  set DefLoc=%@index[%theline,Definition]
  iff %DefLoc gt 0 then
    if %verbose=1 echo The word Definition starts at %DefLoc
    leave
  endiff
enddo
 
iff %DefLoc le 0 then
  echo Could not find Definition in header.
  echo Batch Job Aborted.
  goto eoj
endiff
 
set MethodLen=%@len[%Method]
 
::
:: Look for the %method
::
 
do kount = 1 to %MaxLines
  set theline=%@line[%@path[%_batchname]comcall.tmp,%kount]
  set thename=%@left[%MethodLen,%theline]
  iff  %thename eq %Method then
    if %verbose=1 echo %theline
    set TheLineLen=%@len[%theline]
    if %verbose=1 echo DefLoc=%DefLoc
    if %verbose=1 echo TheLineLen=%TheLineLen
    set Definition=%@instr[%DefLoc,,%theline]
    if %verbose=1 echo %Definition
    leave
  endiff
enddo
 
iff %@len[%Definition] gt 0 then
  if %verbose=1 echo Definition=%Definition
else
  echo Could not find the Definition for %Method.
  iff defined MethodDefFile then
    echo.
    echo You are using %MethodDefFile as your definition file.
    echo.
    echo Unset MethodDefFile and try again.
    echo.
  endiff
  echo Batch Job Aborted.
  goto eoj
endiff
 
if exist %@path[%_batchname]comcall.vbs del %@path[%_batchname]comcall.vbs > nul
 
::
:: Method return type
::
set MethodReturnType=%@word[0,%@unquote[%Definition]]
 
::
:: Method name
::
set MethodName=%@word[1,%@unquote[%Definition]]
 
::
:: How many left parentheses in the "Definition"
::
set LParenthCount=%@count[(,%Definition]
iff %LParenthCount ne 1 then
  echo Error In Definition
  echo %Definition
  goto eoj
else
  if %verbose=1 echo Found 1 left parentheses
endiff
 
::
:: How many right parentheses in the "Definition"
::
set RParenthCount=%@count[),%Definition]
iff %RParenthCount ne 1 then
  echo Error In Definition
  echo %Definition
  goto eoj
else
  if %verbose=1 echo Found 1 right parentheses
endiff
 
::
:: Where does the beginning parentheses begin?
::
set BParenth=%@index[%Definition,(]
 
::
:: Where does the ending parentheses begin?
::
set EParenth=%@index[%Definition,)]
 
::
:: Make sure left is before right parentheses
::
iff %BParenth gt %EParenth then
  echo Definition contains )(, should be ()
  goto eoj
else
  if %verbose=1 echo Definition contains (), okay to continue
endiff
 
::
:: Get the definition without the parentheses
::
set defLength=%@eval[(%EParenth-%BParenth)-1]
set Definition=%@instr[%@eval[%BParenth+1],%defLength,%Definition]
if %verbose=1 echo Definition without parentheses=%Definition
 
::
:: How many arguments does the definition have?
::
iff %@eval[%BParenth+1] eq %EParenth then
  set defArgc=0
  if %verbose=1 echo No Arguments
else
  set defArgc=%@words[,%Definition]
  if %verbose=1 echo Definition has %defArgc argument(s)
endiff
 
::
:: We already know that we have two Batch Parameters,
::  the %dispatch (first) and the %Method (second)
::  The %defArgc + 2 should equal %BatchParameters
::
if %verbose=1 echo defArgc + 2 = %@eval[%defArgc + 2]
if %verbose=1 echo BatchParameters=%BatchParameters
iff %@eval[%defArgc + 2] le %BatchParameters then
  if %verbose=1 echo Everything is okay to proceed
else
  echo %defArgc arguments are required for the definition (%Definition)
  goto eoj
endiff
 
switch %defArgc
  case 0
    gosub 0args
  case 1
    set Arg1=%3
    gosub 1args
  case 2
    set Arg1=%3
    set Arg2=%4
    gosub 2args
  case 3
    set Arg1=%3
    set Arg2=%4
    set Arg3=%5
    gosub 3args
  case 4
    set Arg1=%3
    set Arg2=%4
    set Arg3=%5
    set Arg4=%6
    gosub 4args
  default
    echo You have a definition with more than 4 arguments.
    echo Feel free to expand this batch file to accomodate your requirments.
    goto eoj
endswitch
 
do i = %start to %end
  echo %@line[%_batchname,%i] >> %@path[%_batchname]comcall.vbs
enddo
 
if %verbose=1 type comcall.vbs
 
cscript //nologo %@path[%_batchname]comcall.vbs
 
:eoj
if exist %@path[%_batchname]comcall.tmp del %@path[%_batchname]comcall.tmp > nul
if exist %@path[%_batchname]comcall.vbs del %@path[%_batchname]comcall.vbs > nul
endlocal
quit
 
:0args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName()
endtext
set end=%@eval[%_batchline-3]
return
 
:1args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName(%Arg1)
endtext
set end=%@eval[%_batchline-3]
return
 
:2args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName(%Arg1, %Arg2)
endtext
set end=%@eval[%_batchline-3]
return
 
:3args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName(%Arg1, %Arg2, %Arg3)
endtext
set end=%@eval[%_batchline-3]
return
 
:4args
set start=%@eval[%_batchline+1]
text > nul
set dispatch = wscript.createobject("%dispatch")
wscript.echo dispatch.%MethodName(%Arg1, %Arg2, %Arg3, %Arg4)
endtext
set end=%@eval[%_batchline-3]
return