Resolved: PostMessage to AHK script from EXE?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Resolved: PostMessage to AHK script from EXE?

16 Oct 2013, 10:06

Hi,

I am working on a rather basic C++ application. In this application, I want it to PostMessage to a particular AHK script. The current design is to have the application launched from an AHK script, and that script pass in A_ScriptHwnd as a command-line parameter to the exe.

The two problems I have are:
  1. A_ScriptHwnd gets passed into the command line, so the C++ program has converted it to char*. I am unsure how to properly convert this back to hWnd for use in PostMessage. A simple cast does not work, because the literal text is converted to UINT format for HWND.
  2. Even when I hardcode a HWND for use in PostMessage,the function fails and returns 5 (access is denied).
What's the best way to accomplish what I am trying to do? Is there a better way to do it? The current design is not set in stone, it is just the best one I could think of for my purposes. That purpose is: to send a string of data from the EXE to AHK script.

Thanks in advance.
Last edited by Verdlin on 19 Oct 2013, 08:00, edited 1 time in total.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: PostMessage to AHK script from EXE?

16 Oct 2013, 12:21

For 1 you can also use _ttoi
2 is surely due to UAC, can you turn it off and test?
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Re: PostMessage to AHK script from EXE?

16 Oct 2013, 14:25

Thanks to you both!

The script handle is properly getting converted to hWnd in my exe.

Re: Problem #2. It could be, HotKeyIt. I'm on a W8 computer, and it seems like it's harder to really disable UAC. I had it set to, "never notify" but apparently it was still on. I shut it off by changing a registry setting (http://www.c-sharpcorner.com/UploadFile ... windows-8/)

However, I still am getting the access denied error. Even before Skan replied, I found ChangeWindowMessageFilterEx and starting messing with it. Maybe the DllCall is wrong? Get last error indicates it cannot find the module, and yet ChangeWindowMessageFilterEx returns true.

AHK Script:

Code: Select all

{
	Msgbox % DllCall("ChangeWindowMessageFilterEx", ptr, A_ScriptHwnd, uint, WM_NOTIFY:=78, uint, 1, ptr, 0) "`n" DllCall("GetLastError") ; Output: 1 `n 126
	Run, C:\Test.exe %A_ScriptHwnd%
	return
}
c++

Code: Select all

int main(int argc, char* argv[])
{
  if (argv[1])
  {
	  std::string s = argv[1];
	  int iHwnd = std::stoi(s, 0, 16);
	  HWND hWnd = (HWND)iHwnd;
	  
	  std::cout << "char:" << argv[1] << "|int:" << iHwnd << "|hWnd:" << hWnd << std::endl;
	  std::cout << PostMessage(hWnd, WM_NOTIFY, 0, 0) << std::endl;
	  std::cout << GetLastError() << std::endl;
  }

  std::cout << "Press Enter to quit..." << std::endl;
  std::cin.get();

  return 0;
}
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Re: PostMessage to AHK script from EXE?

16 Oct 2013, 17:56

Update: Tested on Windows Server 2008. Running the same script, ChangeWindowMessageFilterEx returns 1 (true), and GetLastError returns 0.

The C++ GetLastError() still returns 5
lexikos
Posts: 9780
Joined: 30 Sep 2013, 04:07
Contact:

Re: PostMessage to AHK script from EXE?

17 Oct 2013, 03:10

As an aside, DllCall("GetLastError") is roughly equivalent to (pseudo-C) SetLastError(A_LastError), GetLastError(), A_LastError = GetLastError(). After DllCall, you should just use A_LastError.
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Re: PostMessage to AHK script from EXE?

17 Oct 2013, 14:42

Thanks, Lexikos! Will do.

After further research, it seems apparent that I will specifically need to use WM_CopyData. I had originally thought I could use an application-specific message (via RegisterWindowMessage) to send strings, but I do not think this is the case. Reference: http://stackoverflow.com/questions/9844 ... to-another

With the updated script, I get:

ERROR_MESSAGE_SYNC_ONLY
1159 (0x487)
The message can be used only with synchronous operations.

That must be an issue with my compiled exe, correct?

Here is the update

Code: Select all

{
	Msgbox % DllCall("ChangeWindowMessageFilterEx", ptr, A_ScriptHwnd, uint, WM_COPYDATA:=74, uint, 1, ptr, 0) "`n" A_LastError
	Run, C:\Test.exe %A_ScriptHwnd%
	return
}

Code: Select all

int main(int argc, char* argv[])
{
  if (argv[1])
  {
	  std::string s = argv[1];
	  int iHwnd = std::stoi(s, 0, 16);
	  HWND hWnd = (HWND)iHwnd;

	  std::cout << "char:" << argv[1] << "|int:" << iHwnd << "|hWnd:" << hWnd << std::endl;

	  LPCTSTR lpszString = "Hello AHK";
	  COPYDATASTRUCT cds;
	  cds.dwData = 1; // arbitrary
	  cds.cbData = sizeof(TCHAR) * (strlen(lpszString) + 1);
	  cds.lpData = &lpszString;

	  std::cout << PostMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)(LPVOID)&cds) << std::endl;
	  std::cout << GetLastError() << std::endl;
  }

  std::cout << "Press Enter to quit..." << std::endl;
  std::cin.get();

  return 0;
}
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Re: PostMessage to AHK script from EXE?

17 Oct 2013, 21:59

Well, SendMessage gives me no such problem! In the below examples, the AHK script receives the message, but then you're hit with ANSI vs Unicode problems.

The idea for this script + exe bundle is to be able to run it in both AHK ANSI and AHK Unicode. All I want to do is send strings of data the the AHK script, and let the script handle it from there. I just want whatever is the easiest way (i.e. changing settings in the VS project, and/or changing handling in the AHK script). Any guidance here?

By the way, thanks for all the help, everyone. I have always had so much trouble trying to set up my projects in Visual Studio choosing things like MFC vs. Console, Ansi vs Unicode, etc. It's frustrating when all you want is a simple little app. Especially because this little app is a design in a much bigger idea. I'll be posting that within a week or two, hopefully -- I want to start giving back to the AHK community.

Code: Select all

{
    ; At least for me, it is unnecessary to call ChangeMessageFilterEx
	OnMessage(WM_COPYDATA:=74, "OnWMCopyData")
	Run, C:\Test.exe %A_ScriptHwnd%
	return
}

OnWMCopyData(wParam, lParam, msg, hWnd)
{
	Msgbox % StrGet(NumGet(lParam + 2*A_PtrSize))
	return
}

Code: Select all

#include <iostream>
#include "Windows.h"
using namespace std;
int main(int argc, char* argv[])
{
  if (argv[1])
  {
	  string s = argv[1];
	  int iHwnd = stoi(s, 0, 16);
	  HWND hWnd = (HWND)iHwnd;

	  cout << "char:" << argv[1] << "|int:" << iHwnd << "|hWnd:" << hWnd << endl;

	  LPCTSTR lpszString = "Hello AHK";
	  COPYDATASTRUCT cds;
	  cds.dwData = 1; // arbitrary
	  cds.cbData = sizeof(TCHAR) * (strlen(lpszString) + 1);
	  cds.lpData = &lpszString;
	
	  cout << SendMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds) << endl;
	  cout << GetLastError() << endl;
	  // Must be syncronous to use PostMessage
	  //cout << ::PostMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)(LPVOID)&cds) << endl;
	  //cout << GetLastError() << endl;
  }

  return 0;
}
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Re: Resolved: PostMessage to AHK script from EXE?

05 Jan 2014, 16:24

*Sigh* Sometimes the solution is starting you right in the face.

As it turns out, I was translating the string incorrectly.

I was using this:
StringAddress := NumGet(lParam * A_PtrSize)
Instead of this:
StringAddress := NumGet(lParam + 2 * A_PtrSize)

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Bing [Bot] and 130 guests