Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
342 views
in Technique[技术] by (71.8m points)

.net - c# i'm unable to get SendMessage to send a message to a notepad window

I have looked at this question and answer

How to send text to Notepad in C#/Win32?

A slight variation that I think shouldn't matter.. Is that I have a bunch of notepad windows.. So to test this I copied notepad.exe to be notepadd.exe and opened notepadd.exe, so only one of my notepad windows is the notepadd.exe process.

I have this code

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace testsendmessage
{

    public partial class Form1 : Form
    {
        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        [DllImport("User32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

         private void button1_Click(object sender, EventArgs e)
        {
            Process[] notepads = Process.GetProcessesByName("notepadd");
            if (notepads.Length == 0) return;
            if (notepads[0] != null)
            {
                IntPtr child = FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null);
                SendMessage(child, 0x000C, 0, "abcd");
            }
        }
    }
}

It's not touching the notepad window though.

I tried debugging and I see that the notepads array has one item, which is certainly correct.

And it gets within the 'if' and it runs SendMessage(child, 0x000C, 0, "abcd");

But I see nothing appearing in the notepad window

I'm not getting an error from the code it's just nothing appearing in the notepad window.. And I don't really understand winapi stuff much, so i'm not sure how to proceed in trying to solve it?

As you can see it reaches that line, and I can use the watch window to look at the notepads Process array, and at 'child' but I don't know what I should be looking at to determine why it's not sending to the window

enter image description here

Added

New code based on Remy's suggestion

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace testsendmessage
{

    public partial class Form1 : Form
    {
        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("User32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW")]
        public static extern IntPtr SendMessageWStr(IntPtr hWnd, uint uMsg, IntPtr wParam, string lParam);

        const uint WM_SETTEXT = 0x000C;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

         private void button1_Click(object sender, EventArgs e)
        {
            Process[] notepads = Process.GetProcessesByName("notepadd");
            if (notepads.Length == 0) return;
            if (notepads[0] != null)
            {
                IntPtr child = FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null);
                SendMessageWStr(child, WM_SETTEXT, IntPtr.Zero, "abcd");
            }

        }
    }
}

But I still get the same issue that the notepad window was blank before clicking button and is blank after too. It's not sending the text to the notepadd window. Despite the fact that it is reaching that line of code that is meant to send the text to it.

Further addition.

Current code,

I've changed FindWindowEx to FindWindowExW and i've changed new IntPtr(0) to IntPtr.Zero and it still is unresponsive.

I've opened up notepadd.exe from cmd, I see the window there. And of course notepadd.exe in task manger, But clicking the button in my application is not writing any text into that window.

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace testsendmessage
{

    public partial class Form1 : Form
    {
        [DllImport("user32.dll", EntryPoint = "FindWindowExW")]

        public static extern IntPtr FindWindowExW(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("User32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW")]
        public static extern IntPtr SendMessageWStr(IntPtr hWnd, uint uMsg, IntPtr wParam, string lParam);

        const uint WM_SETTEXT = 0x000C;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

         private void button1_Click(object sender, EventArgs e)
        {
            Process[] notepads = Process.GetProcessesByName("notepadd");
            if (notepads.Length == 0) return;
            if (notepads[0] != null)
            {
                IntPtr child = FindWindowExW(notepads[0].MainWindowHandle, IntPtr.Zero, "Edit", null);
                SendMessageWStr(child, WM_SETTEXT, IntPtr.Zero, "abcd");
            }

        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Much credit to Remy. After some troubleshooting I ended up finding the code worked so it's a mystery why I was finding it didn't.

A good troubleshooting step is to try moving the window around with nircmd, so you know you have the handle.

To get the handle of the window, you can use nirsoft winlister, or winspector

You can use nircmd commands like nircmd win close handle 0x00230632 change that 0x00230632 to whatever you find the handle to be. Or better don't close it(otherwise you'll have to reopen it and the new window will have a new handle), so a command like nircmd win move handle 0x00B917AE 80 10 100 100 So you know the handle is right, regardless of any issue with the code.

Winspector also shows the child of the notepad window

enter image description here

Going back to the C# code, you can

skip the child and try writing into the parent, it should write into the title of the window

Try using SendMessage to specify a window directly. You write the handle in decimal rather than hex. e.g. if the handle is 3479948 then

e.g. SendMessage(new IntPtr(3479948), WM_SETTEXT, IntPtr.Zero, "abcdee");

You can also check that notepads[0].MainWindowHandle is picking up the correct value.. the handle shown in winspector.

You can look at the IntPtr child = FindWindowEx(...) line, make sure the 'child' is picking up the child handle.

You can try writing to that one directly with SendMessage. e.g. SendMessage(new IntPtr(1234567), WM_SETTEXT, IntPtr.Zero, "abcdee"); // (if winspector shows the child window to be that handle).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...