Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Call QM programmaticallly from other programs
#1
Is it possible to call QM from other programs and batch files? QM is kind of an "object" that has lots of capabilities, so I would like to call it from other programs as if it was a QM "service."

One way I'd like to use it is from a batch file, where I would call it like any other program:

  rem call qm from a DOS .BAT file
  quickmacros -macroname my-macro-name1

Another way is to call it from Basic as a COM object, using the GetObject call. I'm really interested in this one!
 
sub main
   Dim qm as object
   set qm = GetObject(, "quickmacros.application")
   qm.Run ("my-macro-name-1")
   set qm = nothing
 end sub

A third way would be to reference a quick macros DLL from a Visual Studio project, Excel sheet, Word macro, ... etc.

Is any of this possible, or does QM have to be the top-level boss program that initiates all macros on the basis of user inputs or windows/OS triggers?  Thank you.

I'm just getting started on reading the doc and watching the youtube videos, so please forgive me if the answer is somewhere deeper in the documentation. I haven't seen mention of it so far. Thank you
#2
No COM, no dll, only command line.
Command line text can be created in the Properties dialog, button Cmdline. More info in QM Help topic "Command line parameters".
#3
I'm sorry to hear that no COM interface is available. It would have been wonderful to be able to call QM from other programs. QM has a huge amount of functionality, and it would be useful if other programs could call the macros inside QM. I suppose I could export macros into EXE files and call them through ShellExecute, but that is a crude method and comes with a (temporary) flashing Command Prompt window. Or I could make a BAT file to call QM from the command line and call the BAT file from my other programs with ShellExecute. But still, those are crude methods compared to calling a COM GetObject interface (which seems easy to do for a person of your very advanced skill). Was there a reason or two that you decided not to provide a TLB / COM interface to some of QM's functionality? Thank you
#4
Macros can be executed from any program with ShellExecute or CreateProcess using the command line, directly without bat or command prompt, synchronously or not.
Reason - not many QM users wanted it, so I worked in other directions.
Next major QM version will have a free .NET dll. But not soon.
#5
(03-07-2018, 07:24 PM)Gintaras Wrote: Macros can be executed from any program with ShellExecute or CreateProcess using the command line, directly without bat or command prompt, synchronously or not.
Reason - not many QM users wanted it, so I worked in other directions.
Next major QM version will have a free .NET dll. But not soon.

Thank you. In my case, I was hoping to call QM from the Basic ShellExecute available in Dragon NaturallySpeaking. It is a very limited ShellExecute that does not allow use of nShowCmd to avoid the flashing command prompt window. I suppose I can write my own DLL to implement the chain Dragon -> Basic -> GetObject ("my DLL") -> ShellExecute/CreateProcess -> QM -> macro. I was just hoping that you had a COM interface built over the years. Thank you for your reply.
#6
Or Dragon -> Basic -> GetObject ("my DLL") -> SendMessage(WM_SETTEXT) -> QM -> macro
#7
PS. If I am running an instance of QM and have another program that calls QM on the command line some way, will the running instance of QM interfere with the second QM that is invoked from a batch file? Or if I am running QM and then manually invoke a batch file that calls QM to run a macro, will the two QM instances interfere with each other? Thank you
#8
No, qm always has only 1 normal process (instance). Other qm or qmcl process relays the command line to the main process and exits (qmcl also can wait).
#9
Thank you.
#10
This .NET/COM dll can be used to run macros in QM from other programs and scripts.

Where can be used
In any programming/scripting language through COM.
In C# and other .NET languages directly.
In 32-bit and 64-bit processes.

Setup
The dll uses .NET framework 4. Can be installed any 4.x.x version. If not installed, download from Microsoft and install.
Download the attached zip file. Extract anywhere, for example in QM folder.
Register the dll, unless you'll not use it as a COM component. To register, you can use regasm.exe or this QM code. Note: if you have an old RegisterNetComComponent function, need to update it.
Macro Macro35
Code:
Copy      Help
RegisterNetComComponent "C:\Test\QMSM\QmSendMessage.dll" 2|4
Function RegisterNetComComponent
Code:
Copy      Help
;/
function $dllFile [flags] ;;flags: 1 unregister, 2 create type library (.tlb file), 4 use /codebase

;Registers or unregisters .NET dll as COM component.
;Error if fails.
;QM must be running as administrator.

;REMARKS
;It is possible to use .NET COM components without registration. Use __ComActivator class.

;EXAMPLE
;RegisterNetComComponent "$desktop$\ClassLibrary2.dll" 2|4


str cl so
if(!GetNetRuntimeFolder(cl)) end ES_FAILED

cl.formata("\regasm.exe ''%s'' /nologo" _s.expandpath(dllFile))
if(flags&1) cl+" /u"
else
,if(flags&2) cl+" /tlb"
,if(flags&4) cl+" /codebase"

int i
for i 0 2
,int ec=RunConsole2(cl so)
,err end _error
,so.trim
,if(ec) end so
,if(so.len) out so
,if(i or !_win64) break
,cl.findreplace("\Framework\" "\Framework64\" 5)

How to use in scripts etc
Create COM object "QmSendMessage.QMSM".
To run a macro or function, call the Run function with QM command line, like in the example.

Examples
VBScript example
Code:
Copy      Help
set q = CreateObject("QmSendMessage.QMSM")
q.Run "Q ^ M ^Fun5^", true

You can test it in QM
Macro Macro82
Code:
Copy      Help
str vbs=
;set q = CreateObject("QmSendMessage.QMSM")
;q.Run "Q ^ M ^Fun5^", true
VbsExec vbs

Some limitations
Returning a value is not supported in this version.
The dll is not signed.

Source code
Dll source code in C#, if you want to build it in Visual Studio etc
Code:
Copy      Help
using System;
using System.Runtime.InteropServices;

[module: DefaultCharSet(CharSet.Unicode)]
//these can be in AssemblyInfo.cs, or here if you don't use it:
//[assembly: ComVisible(true)]
//[assembly: Guid("2cd050a0-8337-4d80-b548-56af5b16de04")]
//Also, in project properties, assembly name and default namespace is QmSendMessage, platform can be AnyCPU.

namespace QmSendMessage
{
    [Guid("A4F7F0F0-44BE-4383-8065-6C2636696882")]
    public interface IQMSM
    {
        void Run(string macro, bool wait = false);
    }

    [Guid("BAB07F95-1558-47C6-A6AA-0127BB8F6799"), ClassInterface(ClassInterfaceType.None)]
    public class QMSM :IQMSM
    {
        public void Run(string commandLine, bool wait)
        {
            var w = FindWindow("QM_Editor", null);
            if(w == default(IntPtr)) throw new InvalidOperationException("QM is not running");
            SendMessage(w, WM_SETTEXT, (IntPtr)(wait ? 2 : 1), commandLine);
        }

        [DllImport("user32.dll", EntryPoint = "FindWindowW")]
        internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", EntryPoint = "SendMessageW")]
        internal static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);

        internal const int WM_SETTEXT = 0xC;

    }
}


Attached Files
.zip   QmSendMessage.zip (Size: 2.29 KB / Downloads: 330)
#11
Very great job, thanks to QM developer Heart

I have a question, using this feature, when the macro is packaged into an exe, I do not need to install QM?
#12
Need to install QM.
#13
How to call an item in an AutoText  Huh


Forum Jump:


Users browsing this thread: 2 Guest(s)