-2

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");
            }

        }
    }
}
Community
  • 1
  • 1
barlop
  • 12,887
  • 8
  • 80
  • 109
  • What is the return value of `SendMessage()`? As [documented](https://msdn.microsoft.com/en-us/library/windows/desktop/ms632644.aspx): "*The return value is `TRUE` if the text is set. It is `FALSE` (for an edit control), `LB_ERRSPACE` (for a list box), or `CB_ERRSPACE` (for a combo box) if insufficient space is available to set the text in the edit control. It is `CB_ERR` if this message is sent to a combo box without an edit control.*" – Remy Lebeau Sep 28 '16 at 20:20
  • @RemyLebeau what i'm hoping for at the moment is an adjustment that'd make the code I have into a working demo.. I know very little about the winapi, PInvoke, MarshalAs etc . – barlop Sep 28 '16 at 20:30
  • Try something more like this: `const uint WM_SETTEXT = 0x000C; [DllImport("User32.dll", CharSet=CharSet.Unicode, EntryPoint="SendMessageW")] public static extern IntPtr SendMessageWStr(IntPtr hWnd, uint uMsg, IntPtr wParam, string lParam);` and then you can use `SendMessageWStr(child, WM_SETTEXT, IntPtr.Zero, "abcd");` – Remy Lebeau Sep 28 '16 at 20:37
  • @RemyLebeau updated question – barlop Sep 28 '16 at 20:59
  • There is no `FindWindowEx` function in `user32.dll`, so your `EntryPoint` declaration is wrong. There is `FindWindowExA` for Ansi and `FindWindowExW` for Unicode. And you should be using `IntPtr.Zero` instead of `new IntPtr(0)`. And the standard notepad process name is `"notepad"`, not `"notepadd"`. Do you have multiple notepad processes running at the same time? If so, `GetProcessesByName()` does not provide the processes in any particular order, so make sure you are looking at the same window that you are actually sending the message to. – Remy Lebeau Sep 28 '16 at 21:38
  • @RemyLebeau I have tried FindWindowExA and FindWindowExW and used IntPtr.Zero and still no effect. And as mentioned in my question, I have many notepad.exe windows open so I made a notepadd.exe and only one window, is that one and I can see it open, I know which one that is. – barlop Sep 29 '16 at 01:15
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/124486/discussion-between-barlop-and-remy-lebeau). – barlop Sep 29 '16 at 01:16
  • @remy pinvoke adds the A or W suffix according to charset. new IntPtr(0) is perfectly fine. – David Heffernan Sep 29 '16 at 06:10

1 Answers1

0

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).

barlop
  • 12,887
  • 8
  • 80
  • 109