C# 在c中使用句柄和系统监视程序

C# 在c中使用句柄和系统监视程序,c#,winforms,C#,Winforms,我真的很难理解句柄,即使我尝试了好几天,我也一事无成。我的问题是,我希望我的代码在打开窗口时运行,例如,无标题记事本,因此,当我打开记事本时,我的代码应该正在运行。我有一个windows窗体应用程序,看到一个名为ManagementEventWatcher的事件似乎不起作用。 直到现在我才开始这样做 [DllImport("user32.dll", EntryPoint = "FindWindowEx")] public static extern IntPt

我真的很难理解句柄,即使我尝试了好几天,我也一事无成。我的问题是,我希望我的代码在打开窗口时运行,例如,无标题记事本,因此,当我打开记事本时,我的代码应该正在运行。我有一个windows窗体应用程序,看到一个名为ManagementEventWatcher的事件似乎不起作用。 直到现在我才开始这样做

      [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);  
 private void send_Click(object sender, EventArgs e)
        {
     Process[] notepads = Process.GetProcessesByName("Notepad");
                if (notepads.Length == 0)
                {
                    MessageBox.Show("No test running","Why u do dis?");
                } 
                else if (notepads[0] != null)
                {
                    IntPtr child = FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null);
                    string text = "";
                    foreach (var item in listBox1.Items)
                    {
                        text += item.ToString() ;
                        SendMessage(child, 0x000C, 0, text);

                    }               
                }        
}
当我按下“发送”按钮时,它会将我的listbox1.Items发送到打开的记事本,但这不是我想要的,我希望我的应用程序能够检测到打开的无标题记事本窗口并自动执行该操作。如果有人能向我展示这是如何完成的,并用文档向我解释,这将对我有所帮助

编辑 ----------------------------------------------------------------- 从Matthew Watson的回答中,我得到了大部分问题的答案,答案甚至是更多我没有要求的即兴创作,但我会认真考虑:。但还有一个问题仍然存在。我如何使用ManagementEventWatcher创建事件,以便它能够自动检测何时打开了无标题的记事本,而不是单击按钮。 更新后的代码:

[DllImport("User32", CharSet = CharSet.Auto)]
public static extern int ShowWindow(IntPtr hWnd, int cmdShow);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsIconic(IntPtr hwnd);

[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
 var notepad = Process.GetProcessesByName("Notepad").FirstOrDefault(p => p.MainWindowTitle == "Untitled - Notepad");

            if (notepad != null)
            {
                if (IsIconic(notepad.MainWindowHandle))
                    ShowWindow(notepad.MainWindowHandle, 9);

                SetForegroundWindow(notepad.MainWindowHandle);
                string text = "";

                    foreach (var item in listBox1.Items)
                    {
                       text += item.ToString();

                    }

                Clipboard.SetText(text);
                SendKeys.Send("^V");

            }
-----------------------------------------------------------------

编辑2
对此,您可以使用不同的方法:

查找标题为“无标题-记事本”的记事本窗口 如果将其最小化,则将其取消。 把它带到前台。 用要粘贴到记事本中的文本填充系统剪贴板。 使用SendKeys将Ctrl+V发送到记事本,以粘贴剪贴板内容。 大概是这样的:

[DllImport("User32", CharSet = CharSet.Auto)]
public static extern int ShowWindow(IntPtr hWnd, int cmdShow);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsIconic(IntPtr hwnd);

[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);

private void send_Click(object sender, EventArgs e)
{
    var notepad = Process.GetProcessesByName("Notepad").FirstOrDefault(p => p.MainWindowTitle == "Untitled - Notepad");

    if (notepad != null)
    {
        if (IsIconic(notepad.MainWindowHandle))
            ShowWindow(notepad.MainWindowHandle, 9);

        SetForegroundWindow(notepad.MainWindowHandle);

        Clipboard.SetText("Here's some text to paste into the Notepad window");
        SendKeys.Send("^V");
    }
}
为了确定流程何时启动,您可以使用:

但是,请注意,监视进程启动需要提升权限。换句话说,如果您这样做,那么您的应用程序将需要以管理员身份运行

下面是一个完整的表单实现示例,当记事本打开时,它会将一些文本粘贴到记事本中:

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

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var query = new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName = 'Notepad.exe'");
            var mew = new ManagementEventWatcher(query) {Query = query};
            mew.EventArrived += (sender, args) => { notepadStarted(); };
            mew.Start();
        }

        void notepadStarted()
        {
            BeginInvoke(new Action(pasteIntoNotepad));
        }

        [DllImport("User32", CharSet = CharSet.Auto)]
        public static extern int ShowWindow(IntPtr hWnd, int cmdShow);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsIconic(IntPtr hwnd);

        [DllImport("user32.dll")]
        public static extern int SetForegroundWindow(IntPtr hWnd);

        void pasteIntoNotepad()
        {
            var notepad = Process.GetProcessesByName("Notepad").FirstOrDefault(p => p.MainWindowTitle == "Untitled - Notepad");

            if (notepad != null)
            {
                notepad.WaitForInputIdle();

                if (IsIconic(notepad.MainWindowHandle))
                    ShowWindow(notepad.MainWindowHandle, 9);

                SetForegroundWindow(notepad.MainWindowHandle);

                Clipboard.SetText("Here's some text to paste\r\ninto the Notepad window");
                SendKeys.Send("^V");
            }
        }
    }
}
您需要以管理员身份运行此程序,否则它将引发拒绝访问异常


还请注意,这不会处理多个具有相同标题的记事本实例—无标题记事本

您正在寻找名为Notepad的进程,因此您当然会找到所有进程。然后,您必须通过查找每个进程的主窗口(如果有)及其标题来筛选该列表。假设我将永远不会打开多个主窗口。让我们从那里开始。您说您想要一个标题为“无标题-记事本”的窗口,但您不在程序中测试该窗口。因为在我的程序中,我按进程进行测试,我想用窗口的实际名称来测试,它不是这样工作的。因为正如我说的,我真的不明白这一切是如何工作的,我真的试着去理解,但它只是不起作用。这就是为什么我在这里寻求帮助如果你的问题被赋予了一个窗口的句柄,我如何得到它的标题?而不是问这个问题,或者在谷歌上输入。这就产生了这个链接:有一件事还没有回答,我不想用发送按钮发送我的信息,我就是这样做的,因为我不知道如何使用system watcher。我希望我的应用程序能够自动检测到我打开了记事本并执行代码。@JohnPietrar您可以使用ManagementEventWatcher来实现这一点-我看看是否可以找到一些示例代码。我还需要一些指令或程序集引用吗?因为它引发了以下错误:找不到类型或命名空间名称“WQLVENTQUERY”是否缺少using指令或程序集引用?@JohnPietrar是的,您需要添加对系统的引用。Management@JohnPietrar你读了我用粗体写的答案中的文字了吗?因为它非常重要;
using System;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var query = new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName = 'Notepad.exe'");
            var mew = new ManagementEventWatcher(query) {Query = query};
            mew.EventArrived += (sender, args) => { notepadStarted(); };
            mew.Start();
        }

        void notepadStarted()
        {
            BeginInvoke(new Action(pasteIntoNotepad));
        }

        [DllImport("User32", CharSet = CharSet.Auto)]
        public static extern int ShowWindow(IntPtr hWnd, int cmdShow);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsIconic(IntPtr hwnd);

        [DllImport("user32.dll")]
        public static extern int SetForegroundWindow(IntPtr hWnd);

        void pasteIntoNotepad()
        {
            var notepad = Process.GetProcessesByName("Notepad").FirstOrDefault(p => p.MainWindowTitle == "Untitled - Notepad");

            if (notepad != null)
            {
                notepad.WaitForInputIdle();

                if (IsIconic(notepad.MainWindowHandle))
                    ShowWindow(notepad.MainWindowHandle, 9);

                SetForegroundWindow(notepad.MainWindowHandle);

                Clipboard.SetText("Here's some text to paste\r\ninto the Notepad window");
                SendKeys.Send("^V");
            }
        }
    }
}