在c#中使用句柄和系统观察程序

时间:2016-09-23 08:43:34

标签: c# winforms

我很难理解句柄,而且我几乎没有到达任何地方,即使我试图这样做几天。我的问题是这样的,我希望我的代码在窗口打开时运行,例如" Untitled - Notepad" ,所以当我打开记事本时,我的代码应该正在运行。我有一个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发送到打开的记事本,但这不是我想要的,我希望我的应用程序检测打开的Untitled - Notepad窗口并自动执行此操作。它会有所帮助如果有人能告诉我这是怎么做的,我也可以通过文件向我解释。

修改

---------------------------------------- -------------------------------------------------- ---------------------------------------

来自Matthew Watson的回答我得到了大部分问题的回答,更多的即兴创作,我没有要求,但我会深深地接受他们:)。但仍有一个问题仍然存在。我怎样才能创建一个活动使用ManagementEventWatcher,这样它会自动检测何时打开Untitled - Notepad而不是点击按钮。

更新后的代码:

[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

enter image description here

1 个答案:

答案 0 :(得分:4)

您可以使用不同的方法:

  1. 找一个标题为“Untitled - Notepad”的记事本窗口
  2. 如果它被最小化,请不要小心。
  3. 把它带到前台。
  4. 使用要粘贴到记事本中的文本填充系统剪贴板。
  5. 使用SendKeys()将Ctrl + V发送到记事本,以粘贴剪贴板内容。
  6. 这样的事情:

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

    为了确定流程何时开始,您可以使用class ManagementEventWatcher

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

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

    这是一个完整的示例Form实现,它会在打开时将一些文本粘贴到记事本中:

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

    您需要以管理员身份运行它,否则会抛出拒绝访问的异常。

    另请注意,这不会处理所有具有相同标题“无标题 - 记事本”的记事本的多个实例!