From WikiChip
Difference between revisions of "mirc/sendmessage"
< mirc

m (Initializing communication)
(revert spam)
 
(67 intermediate revisions by 24 users not shown)
Line 1: Line 1:
You can use SendMessage to communicate with mIRC from your external application, in your dll for example.
+
{{mirc title|SendMessage()}}
 
+
The {{Win32|SendMessage()}} function can be used to communicate with mIRC from your external [[process]] (e.g. another program or a [[dll]]). mIRC provides a number of private [[Window Messages]] to evaluate or execute commands and identifiers.
= Initializing communication =
 
  
 +
== Initializing communication ==
 
The external programs that send these messages must create a mapped file with the [http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537%28v=vs.85%29.aspx CreateFileMapping()] function:
 
The external programs that send these messages must create a mapped file with the [http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537%28v=vs.85%29.aspx CreateFileMapping()] function:
  
  CreateFileMapping(
+
CreateFileMapping(
    _In_      HANDLE hFile,
+
  _In_      HANDLE hFile,
    _In_opt_  LPSECURITY_ATTRIBUTES lpAttributes,
+
  _In_opt_  LPSECURITY_ATTRIBUTES lpAttributes,
    _In_      DWORD flProtect,
+
  _In_      DWORD flProtect,
    _In_      DWORD dwMaximumSizeHigh,
+
  _In_      DWORD dwMaximumSizeHigh,
    _In_      DWORD dwMaximumSizeLow,
+
  _In_      DWORD dwMaximumSizeLow,
    _In_opt_  LPCTSTR lpName
+
  _In_opt_  LPCTSTR lpName
  );
+
);
  
 
* Use INVALID_HANDLE_VALUE for the hFile parameter, which basically allows the sytem to handle the file for us.
 
* Use INVALID_HANDLE_VALUE for the hFile parameter, which basically allows the sytem to handle the file for us.
Line 25: Line 25:
 
'''Note''': To prevent simultaneous access to the mapped file, your code must check whether the mapped file exists or not before using it. If it exists, you should assume that it is in use by another program, and should try again later.
 
'''Note''': To prevent simultaneous access to the mapped file, your code must check whether the mapped file exists or not before using it. If it exists, you should assume that it is in use by another program, and should try again later.
  
= Communicating =
+
== Communicating ==
  
== Performing Commands ==
+
After creating the mapped file, you need to write to that file the line mIRC will receive, see the examples to get an idea about how to write to that file.
 +
 
 +
=== Performing Commands ===
  
 
The following call to SendMessage() makes mIRC perform the commands that you specify:
 
The following call to SendMessage() makes mIRC perform the commands that you specify:
  
SendMessage(mHwnd, WM_MCOMMAND, cMethod, cIndex)
+
'''Note''': the 'command' is placed into the editbox and enter is pressed is the exact behavior, this can be used to send IRC messages by not prefixing the command with slashes, but you must prefix it with at least one slash then, if you want to execute a command.
  
* '''mHwnd''' - the handle of the main mIRC window, or the handle of a Channel, Query, etc. window.
+
SendMessage(mHwnd, WM_MCOMMAND, cMethod, cIndex)
* '''WM_MCOMMAND''' - which should be defined as WM_USER + 200  
+
 
* '''cMethod''' - how mIRC should process the message, where:
+
* '''mHwnd''' - The handle of the main mIRC window, or the handle of a Channel, Query, etc. window.
** 1 = as if typed in editbox (default)
+
* '''WM_MCOMMAND''' - Which should be defined as WM_USER + 200  
** 2 = as if typed in editbox, send as plain text
+
* '''cMethod''' - How mIRC should process the message, where:
** 4 = use flood protection if turned on, can be or'd with 1 or 2
+
** 1 = As if typed in editbox (default).
** 8 = use unicode text
+
** 2 = As if typed in editbox, send as plain text
 +
** 4 = Use flood protection if turned on, can be or'd with 1 or 2, and 8
 +
** 8 = Use unicode text. For backward compatibility reason, mIRC takes the data in the mapped file as ANSI by default, if you are willing to use unicode, you must use this. This can be or'd with 1 or 2, and 4.
  
 
* '''cIndex''' - If you created a mapped filename of the form "mIRCN", this is where you specify the N parameter to use, if cIndex is 0, the filename must be "mIRC".
 
* '''cIndex''' - If you created a mapped filename of the form "mIRCN", this is where you specify the N parameter to use, if cIndex is 0, the filename must be "mIRC".
Line 45: Line 49:
 
This call returns 1 on success, 0 if it fails.
 
This call returns 1 on success, 0 if it fails.
  
== Evaluating Identifiers and Variables ==
+
=== Evaluating Identifiers and Variables ===
  
 
The following call to SendMessage() makes mIRC evaluate the contents of any line that you specify:
 
The following call to SendMessage() makes mIRC evaluate the contents of any line that you specify:
  
SendMessage(mHwnd, WM_MEVALUATE, cMethod, cIndex)
+
SendMessage(mHwnd, WM_MEVALUATE, cMethod, cIndex)
  
* '''mHwnd''' - the handle of the main mIRC window, or the handle of a Channel, Query, etc. window.
+
* '''mHwnd''' - The handle of the main mIRC window, or the handle of a Channel, Query, etc. window.
* '''WM_MEVALUATE''' - should be defined as WM_USER + 201
+
* '''WM_MEVALUATE''' - Should be defined as WM_USER + 201
* '''cMethod''' - how mIRC should process the message, where:
+
* '''cMethod''' - How mIRC should process the message, where:
** 8 = use unicode text
+
** 8 = Use unicode text. For backward compatibility reason, mIRC takes the data in the mapped file as ANSI by default, if you are willing to use unicode, you must use this.
  
 
* '''cIndex''' - If you created a mapped filename of the form "mIRCN", this is where you specify the N parameter to use, if cIndex is 0, the filename must be "mIRC".
 
* '''cIndex''' - If you created a mapped filename of the form "mIRCN", this is where you specify the N parameter to use, if cIndex is 0, the filename must be "mIRC".
Line 60: Line 64:
 
This call returns 1 on success, 0 if it fails.
 
This call returns 1 on success, 0 if it fails.
  
= Remote Event Context =
+
== Remote Event Context ==
  
If during a remote event, such as on TEXT, your script calls a DLL which then uses SendMessage() to execute a command or evaluate an identifier, you can tell SendMessage() to execute in the context of that remote event.
+
If during a remote event, such as on TEXT, your script calls a DLL which then uses {{Win32|SendMessage()}} to execute a command or evaluate an identifier, you can tell {{Win32|SendMessage()}} to execute in the context of that remote event.
  
 
During a remote event, a {{mIRC|$eventid}} identifier is set to a unique value to identify the event. This can be passed to a DLL which can then pass it back to mIRC using:
 
During a remote event, a {{mIRC|$eventid}} identifier is set to a unique value to identify the event. This can be passed to a DLL which can then pass it back to mIRC using:
  
SendMessage(mHwnd, WM_MCOMMAND, MAKEWPARAM(cMethod, cEventId), cIndex)
+
SendMessage(mHwnd, WM_MCOMMAND, MAKEWPARAM(cMethod, cEventId), cIndex)
  
 
This will cause the command/evaluation to execute in the context of the remote event identified by cEventId. If cEventId is 0, this indicates a non-remote event.
 
This will cause the command/evaluation to execute in the context of the remote event identified by cEventId. If cEventId is 0, this indicates a non-remote event.
  
= Extended Version Information =
+
== Extended Version Information ==
  
 
If '''cMethod''' is set to -1, you can set '''cIndex''' to:
 
If '''cMethod''' is set to -1, you can set '''cIndex''' to:
Line 76: Line 80:
 
* '''-2''' - to receive the cMethod options that are supported.
 
* '''-2''' - to receive the cMethod options that are supported.
  
= Extended Error Information =
+
== Extended Error Information ==
  
 
If cMethod is or'd with the value 16, this will make SendMessage() return more useful error values instead of just 0 for failure and 1 for success. The return values are:
 
If cMethod is or'd with the value 16, this will make SendMessage() return more useful error values instead of just 0 for failure and 1 for success. The return values are:
Line 85: Line 89:
 
** '''8''' - Bad eventid.
 
** '''8''' - Bad eventid.
 
** '''16''' - Bad server.
 
** '''16''' - Bad server.
** '''32''' - Bad code/script.
+
** '''32''' - Bad script - means that the script does not exist
 
** '''64''' - Disabled (if disabled in lock dialog).
 
** '''64''' - Disabled (if disabled in lock dialog).
  
[[Category:MIRC]]
+
1 alone means that a script error occured, 16 and 32 can only happen if you use $eventid in SendMessage() in the context of a remote event but the script from which it was called no longer exist.
[[Category:Interprocess communication]]
+
 
 +
= Examples =
 +
<source lang="c">
 +
#include <stdio.h>
 +
#include <windows.h>
 +
#define WM_MCOMMAND WM_USER + 200
 +
#define WM_MEVALUATE WM_USER + 201
 +
HANDLE file;
 +
LPSTR str;
 +
 
 +
int main(int argc, char * argv[])
 +
{
 +
char* command = "//echo -a Hello world";
 +
char* evaluation = "m $+ $upper(irc)";
 +
file = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, L"mIRC");
 +
if (file == NULL)
 +
exit(0);
 +
str = (LPSTR)MapViewOfFile(file, FILE_MAP_ALL_ACCESS, 0, 0, 0);
 +
if (str == NULL)
 +
exit(0);
 +
HWND mhwnd = (HWND)atoi(argv[1]);
 +
//send //echo -s Hello world to mIRC
 +
strcpy_s(str, 4096, command);
 +
SendMessage(mhwnd, WM_MCOMMAND, 1, 0);
 +
//Ask mIRC to evaluate and send back the result
 +
strcpy_s(str, 4096, evaluation);
 +
SendMessage(mhwnd, WM_MEVALUATE, 0, 0);
 +
printf("%s", str);
 +
}
 +
</source>
 +
You must pass the handle of the main mIRC window or a valid channel, query etc window as the first parameter of the program in the command line for it to work.
 +
[[Category:mIRC|sendmessage]]
 +
[[Category:interprocess communication]]

Latest revision as of 21:49, 25 April 2024

The SendMessage() function can be used to communicate with mIRC from your external process (e.g. another program or a dll). mIRC provides a number of private Window Messages to evaluate or execute commands and identifiers.

Initializing communication[edit]

The external programs that send these messages must create a mapped file with the CreateFileMapping() function:

CreateFileMapping(
  _In_      HANDLE hFile,
  _In_opt_  LPSECURITY_ATTRIBUTES lpAttributes,
  _In_      DWORD flProtect,
  _In_      DWORD dwMaximumSizeHigh,
  _In_      DWORD dwMaximumSizeLow,
  _In_opt_  LPCTSTR lpName
);
  • Use INVALID_HANDLE_VALUE for the hFile parameter, which basically allows the sytem to handle the file for us.
  • Use NULL for lpAttributes, for a default security.
  • Use PAGE_READWRITE for flProtect, to be able to read and write from/to the file.
  • Use 0 for dwMaximumSizeHigh and 4096 for dwMaximumSizeLow to indicate a file of that size

Note: The mapped file must be at least 4096 bytes.

  • lpName is the name of the file, in previous version of mIRC, this parameter had to be "mIRC", you certainly can see the limitation with this, so it was extended, you can now specify a name of the form "mIRCN" where N is a number. You can also still use mIRC of course.

Note: To prevent simultaneous access to the mapped file, your code must check whether the mapped file exists or not before using it. If it exists, you should assume that it is in use by another program, and should try again later.

Communicating[edit]

After creating the mapped file, you need to write to that file the line mIRC will receive, see the examples to get an idea about how to write to that file.

Performing Commands[edit]

The following call to SendMessage() makes mIRC perform the commands that you specify:

Note: the 'command' is placed into the editbox and enter is pressed is the exact behavior, this can be used to send IRC messages by not prefixing the command with slashes, but you must prefix it with at least one slash then, if you want to execute a command.

SendMessage(mHwnd, WM_MCOMMAND, cMethod, cIndex)
  • mHwnd - The handle of the main mIRC window, or the handle of a Channel, Query, etc. window.
  • WM_MCOMMAND - Which should be defined as WM_USER + 200
  • cMethod - How mIRC should process the message, where:
    • 1 = As if typed in editbox (default).
    • 2 = As if typed in editbox, send as plain text
    • 4 = Use flood protection if turned on, can be or'd with 1 or 2, and 8
    • 8 = Use unicode text. For backward compatibility reason, mIRC takes the data in the mapped file as ANSI by default, if you are willing to use unicode, you must use this. This can be or'd with 1 or 2, and 4.
  • cIndex - If you created a mapped filename of the form "mIRCN", this is where you specify the N parameter to use, if cIndex is 0, the filename must be "mIRC".

This call returns 1 on success, 0 if it fails.

Evaluating Identifiers and Variables[edit]

The following call to SendMessage() makes mIRC evaluate the contents of any line that you specify:

SendMessage(mHwnd, WM_MEVALUATE, cMethod, cIndex)
  • mHwnd - The handle of the main mIRC window, or the handle of a Channel, Query, etc. window.
  • WM_MEVALUATE - Should be defined as WM_USER + 201
  • cMethod - How mIRC should process the message, where:
    • 8 = Use unicode text. For backward compatibility reason, mIRC takes the data in the mapped file as ANSI by default, if you are willing to use unicode, you must use this.
  • cIndex - If you created a mapped filename of the form "mIRCN", this is where you specify the N parameter to use, if cIndex is 0, the filename must be "mIRC".

This call returns 1 on success, 0 if it fails.

Remote Event Context[edit]

If during a remote event, such as on TEXT, your script calls a DLL which then uses SendMessage() to execute a command or evaluate an identifier, you can tell SendMessage() to execute in the context of that remote event.

During a remote event, a $eventid identifier is set to a unique value to identify the event. This can be passed to a DLL which can then pass it back to mIRC using:

SendMessage(mHwnd, WM_MCOMMAND, MAKEWPARAM(cMethod, cEventId), cIndex)

This will cause the command/evaluation to execute in the context of the remote event identified by cEventId. If cEventId is 0, this indicates a non-remote event.

Extended Version Information[edit]

If cMethod is set to -1, you can set cIndex to:

  • -1 - to receive the mIRC version number.
  • -2 - to receive the cMethod options that are supported.

Extended Error Information[edit]

If cMethod is or'd with the value 16, this will make SendMessage() return more useful error values instead of just 0 for failure and 1 for success. The return values are:

  • 0 - Success.
  • 1 - Failure, You can OR that value to get more specific errors:
    • 2 - Bad mapped filename.
    • 4 - Bad mapped file size.
    • 8 - Bad eventid.
    • 16 - Bad server.
    • 32 - Bad script - means that the script does not exist
    • 64 - Disabled (if disabled in lock dialog).

1 alone means that a script error occured, 16 and 32 can only happen if you use $eventid in SendMessage() in the context of a remote event but the script from which it was called no longer exist.

Examples[edit]

#include <stdio.h>
#include <windows.h>
#define WM_MCOMMAND WM_USER + 200
#define WM_MEVALUATE WM_USER + 201
HANDLE file;
LPSTR str;

int main(int argc, char * argv[])
{
	char* command = "//echo -a Hello world";
	char* evaluation = "m $+ $upper(irc)";
	file = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, L"mIRC");
	if (file == NULL)
		exit(0);
	str = (LPSTR)MapViewOfFile(file, FILE_MAP_ALL_ACCESS, 0, 0, 0);
	if (str == NULL)
		exit(0);
	HWND mhwnd = (HWND)atoi(argv[1]);
	//send //echo -s Hello world to mIRC
	strcpy_s(str, 4096, command);
	SendMessage(mhwnd, WM_MCOMMAND, 1, 0);
	//Ask mIRC to evaluate and send back the result
	strcpy_s(str, 4096, evaluation);
	SendMessage(mhwnd, WM_MEVALUATE, 0, 0);
	printf("%s", str);
}

You must pass the handle of the main mIRC window or a valid channel, query etc window as the first parameter of the program in the command line for it to work.