2

I have compiled a bunch of online resources that got me to here. Hopefully what I have is close. Unfortunately I have no Windows Programming experience. I come from a Linux background. I am also new to alien for Lua, but I know Lua well enough.

What I want to do is send a simple "Hello World" with sendMessage() from the Win32 API to a running Notepad.exe window.

I got the process ID from the command prompt with the following command:

tasklist /FI "IMAGENAME eq notepad.exe" /FI "USERNAME eq user"

notepad PID

And I got the message to send code of 0x000C from here.

So far this is what I have:

require "luarocks.require"
require "alien"

myTestMessage = 0x000C -- Notepad "Set text" id
notepadPID = 2316      -- Notepad Process ID

-- Prototype the SendMessage function from User32.dll
local SendMessage= alien.User32.SendMessageA
SendMessage:types{ret ='long', abi = 'stdcall','long','long','string','string'}

-- Prototype the FindWindowExA function from User32.dll
local FindWindowEx = alien.User32.FindWindowExA
FindWindowEx:types{ret = 'long', abi = 'stdcall', 'long', 'long', 'string', 'string'}

-- Prototype the GetWindowThreadProcessID function from User32.dll
local GetWindowThreadProcessId = alien.User32.GetWindowThreadProcessId
GetWindowThreadProcessId:types{ret = 'long', abi = 'stdcall', 'long', 'pointer'}

local buffer = alien.buffer(4) -- This creates a 4-byte buffer

local threadID = GetWindowThreadProcessId(notepadPID, buffer) -- this fills threadID and our 4-byte buffer

local longFromBuffer = buffer:get(1, 'long') -- this tells that I want x bytes forming a 'long' value and starting at the first byte of the
                             -- 'buffer' to be in 'longFromBuffer' variable and let its type be 'long'

local handle = FindWindowEx(threadID, "0", "Edit", nil); -- Get the handle to send the message to

local x = SendMessage(handle, myTestMessage, "0", "Hello World!") -- Actually send the message

A lot of this code was pieced together from the Lua alien documents, msdn, and some Google searches (namely this result).

Is there anyone out there who could be a hero and explain to me what i'm doing wrong, and how I should go about this. And, most importantly, why!

Community
  • 1
  • 1
MrHappyAsthma
  • 6,332
  • 9
  • 48
  • 78

2 Answers2

2

I eventually found a simpler way to do this using both FindWindow and FindWindowEX from the Windows API. This way you can find correct handles to the parent and children processes of Notepad.

-- Require luarocks and alien which are necessray for calling Windows functions
require "luarocks.require"
require "alien"

local SendMessage= alien.User32.SendMessageA
SendMessage:types{ret ='long', abi = 'stdcall','long','long','string','string'}

local FindWindowEx = alien.User32.FindWindowExA
FindWindowEx:types{ret = 'long', abi = 'stdcall', 'long', 'long', 'string', 'string'}

local FindWindow = alien.User32.FindWindowA
FindWindow:types{ret = 'long', abi = 'stdcall', 'string', 'string'}

local notepadHandle = FindWindow("Notepad", NULL )

local childHandle = FindWindowEx(notepadHandle, "0", "Edit", nil)

local x = SendMessage(childHandle, "0x000C", "0", "Hello World!") -- Actually send the message
MrHappyAsthma
  • 6,332
  • 9
  • 48
  • 78
1

You are misusing GetWindowThreadProcessId() and FindWindowEx(). The first parameter to both of them is an HWND handle to the desired window, but you are passing a process ID to GetWindowThreadProcessId() and a thread ID to FindWindowEx(), both of which are wrong.

There is no straightforward way to get an HWND from a process ID. You would have to use EnumWindows() to loop through the currently running windows, calling GetWindowThreadProcessId() on each one until you find a matching process ID to the one you already have.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770