Project

General

Profile

SendMessage() Support

Added by Hans Müller 2 months ago

Hey is there anyway to use the SendMessage function from mIRC? https://www.mirc.com/help/html/index.html?sendmessage.html

I tried a lot of code (with the help of ChatGPT and the sigmirc.exe source code) but it isn't working at all.

Is there some documentation on what parameter must be included? Or is it working at all with AdiIRC?

Thank you!
Hans


Replies (29)

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

It should work the same as mirc, where mHwnd is the handle of the main adiirc window, which you can get with $window(-2).hwnd.

RE: SendMessage() Support - Added by Hans Müller 2 months ago

Is there a way I can use to send it to all AdiIRC windows?

In my use case I want to use the /signal command.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

Depends on what you mean by all adiirc windows, if you mean multiple instances of adiirc, you could write the hwnd from each instance to a file or something like that.

If you mean to multiple channel inside a single instance, you can use $window(#channel).hwnd to get the handle for each one.

Also if you mean channel windows, you could just loop $channl or $window inside the script from your mapped file that you attach to SendMessage.

RE: SendMessage() Support - Added by Hans Müller 2 months ago

Example code:

#include <windows.h>

#define WM_MCOMMAND (WM_USER+200)

#define MAPSZ 4096

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int show) {
HANDLE hmap, hmutex;
HWND hwnd = NULL;
char *ptr;
int len;

/* make sure there's at least a signal name on the commandline */
if (!*cmdline) {
DWORD written;
char usage[] = "usage: sigmadiirc &lt;signal&gt; [data]\r\n";
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), usage, lstrlen(usage),
&written, NULL);
return 0;
}
/* create a file mapping */
hmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, MAPSZ, "AdiIRC");
/* check to see the map is newly created, now replaced with mutex below */
/* map a view of the file mapping onto memory */
ptr = (char *)MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (!ptr) {
CloseHandle(hmap);
return 1;
}
/* create or open a mutex that will protect the shared memory access */
if ((hmutex = CreateMutex(NULL, FALSE, "AdiIRC_SendMessage")) != NULL) {
/* wait for this mutex to be released - if it is currently locked, wait */
WaitForSingleObject(hmutex, INFINITE);
/* store the signal command into memory */
len = lstrlen(lstrcpy(ptr, "/.signal "));
lstrcpyn(ptr + len, cmdline, MAPSZ - len);
/* send the signal to all AdiIRC windows */
while ((hwnd = FindWindowEx(NULL, hwnd, "AdiIRC", NULL)) != NULL)
SendMessage(hwnd, WM_MCOMMAND, 1, NULL);
/* get rid of the mutex */
ReleaseMutex(hmutex);
CloseHandle(hmutex);
}
/* and clean up the file mapping */
UnmapViewOfFile(ptr);
CloseHandle(hmap);
return 0;
}

If i use that code with mIRC it works. My goal is it to send a message to AdiIRC (one instance), AdiIRC has a on signal event. lets call it test:

on *:signal:test:{
/msg #testchannel $1-
}

But sadly it looks like my compiled exe isnt sending anything to AdiIRC.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

Have you verified that " while ((hwnd = FindWindowEx(NULL, hwnd, "AdiIRC", NULL)) != NULL)" is finding any windows and if so, that the hwnd matches $window(-2).hwnd ?

If the hwnd's are correct, check File -> Rawlog -> Debug in one of the instances, see if there are any "ExternalMessage" errors.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

Also I can't quite make it our, but the mapped file should have the same name as mirc, e.g it should start with "mIRC".

RE: SendMessage() Support - Added by Hans Müller 2 months ago

Tried it with mIRC still not working rawlog shows absolutely nothing so it seems the window is not found but i don't know why.

AdiIRC should be the window name.

I don't get it.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

I can't seem to make FindWindow/FindWindowEx work either, I think it's because it's a .NET app so the name is winforms.xx.xxx or something like that.

You could try scan proccess for AdiIRC.exe instead and get the MainWindowHandle. not sure exactly what the c++ equivalent is.

RE: SendMessage() Support - Added by Hans Müller 2 months ago

Well i tried it with:

EnumWindows((hWnd, lParam) =>
{
StringBuilder windowTitle = new StringBuilder(256);
GetWindowText(hWnd, windowTitle, windowTitle.Capacity);
if (windowTitle.ToString().Contains("AdiIRC"))
{
hwnd = hWnd;
return false; // Stop enumeration
}

Window found. Sending message...
Message sent.

But nothing happens. I tried it with ShowWindow(hwnd, SW_RESTORE); to just look if the window gets activated when minimized, well that is working but sending /signal test test1234 not.

I don't understand it. Normaly it should send the command to the window.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

Do you see anything in the rawlog?

RE: SendMessage() Support - Added by Hans Müller 2 months ago

No nothing. Like it didn't find the window but well it is found. Very strange.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

I'll see if I can make something that mimics what you are doing and do some tests.

RE: SendMessage() Support - Added by Hans Müller 2 months ago

I'll tried the direct window handle and it is also not working.

Would be cool :) because i'am running out of ideas.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

It seems to work. Have you tried something simple like "/echo -a hello world" in case there is a problem with the signal script.

RE: SendMessage() Support - Added by Hans Müller 2 months ago

Yes but also not working. Do you have a code example?

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

Only in c#, I don't know much about c++.

But I verified that using the same parameters for SendMessage API, as you do, is working.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

I'll make a debug build of AdiIRC, maybe it will discover something.

RE: SendMessage() Support - Added by Hans Müller 2 months ago

That is strange tried it on Win 11 and Windows 10 (VM) but didn't work.

Can you share the C# code? Maybe i can try it out.

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

https://adiirc.com/build/1713019486/AdiIRC.exe (64 bit)
https://adiirc.com/build/1713019486/AdiIRC32.exe (32 bit)

It should log all the steps related to WM_MCOMMAND to Rawlog.

C¤ code:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

using (var mappedFile = MemoryMappedFile.CreateNew("mIRC1", 8192))
{
    using (Stream stream = mappedFile.CreateViewStream())
        {
            byte[] bytes = Encoding.UTF8.GetBytes("/echo -ag hello world");
                stream.Write(bytes, 0, bytes.Length);
    }

        SendMessage(new IntPtr(hwnd), WM_MCOMMAND, 1, 1);
}

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

Probably need these as well:

private const int WM_USER = 0x400;

private const int WM_MCOMMAND = WM_USER + 200;

RE: SendMessage() Support - Added by Hans Müller 2 months ago

I can't compile it hm

RE: SendMessage() Support - Added by Per Amundsen 2 months ago

It's not a complete program, just the code that perform the action.

I have attached a full console app, in visual studio 2019 format.

RE: SendMessage() Support - Added by Hans Müller 2 months ago

Thank you! I will look into it, iam very new to C# and C++ Stuff so thank you very much for helping out :)

RE: SendMessage() Support - Added by Hans Müller 2 months ago

Code for compiling:

Win 10:
https://pastebin.com/FY8AxKqr

All Windows:
https://pastebin.com/2AuJ3hhR

It searchs for "AdiIRC" in the windows and send the command to all windows.

The Win 10 method uses the classname of AdiIRC but here something strange happened.

Win 10: WindowsForms10.Window.8.app.0.282af8c_r6_ad1
Win 7: WindowsForms10.Window.8.app.0.282af8c_r12_ad1

Can somebody explain to me why? Should it be the same classname? Why is there a difference between the 2 Windows Versions.
I thought the classname is hardcoded in the programm itself?

Also childwindow (atleast i believe so):
Win 10: WindowsForms10.RichEdit50W.app.0.282af8c_r6_ad11
Win 7: WindowsForms10.RichEdit20W.app.0.282af8c_r12_ad11

Is there a reason why this happens? Also it seems like every Window has a different WindowsForms10.

Btw thank you for the code! It helped me a lot :)

RE: SendMessage() Support - Added by Hans Müller 2 months ago

Added 2 compiled .exe versions

Compiled with csc.exe from Microsoft.NET\Framework64\v4.0.30319\

Maybe someone has the same issues like me so he can just use the compiled .exe :)

(1-25/29)