0

I'm trying to monitor clipboard changes with a .NET console appilcation. Therefore I use the "SharpClipboard" library and the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WK.Libraries.SharpClipboardNS;
using System.Threading;
using System.Diagnostics;

namespace MeinKasten2Printer
{
    class Program
    {
        [STAThreadAttribute]
        static void Main(string[] args)
        {
            var clipboard = new SharpClipboard();

            // Attach your code to the ClipboardChanged event to listen to cuts/copies.
            clipboard.ClipboardChanged += ClipboardChanged;



        }

        public static void ClipboardChanged(Object sender, SharpClipboard.ClipboardChangedEventArgs e)
        {
            // Is the content copied of text type?
            if (e.ContentType == SharpClipboard.ContentTypes.Text)
            {
                // Get the cut/copied text.
                Debug.WriteLine(e.Content.ToString());
            }
   
        }
    }
}

The problem is that the application is immediately closing after execution. What I am doing wrong? It should output all the text changes.

Patrick Grebe
  • 111
  • 2
  • 14
  • `The problem is that the application is immediately closing after execution.` that's what you told it to do. Nothing happens after the event handler is added so `Main` exits immediately and the application terminates – Panagiotis Kanavos Jan 20 '21 at 08:08
  • Add Console.ReadLine(); as last line in main method – Sunil Jan 20 '21 at 08:09
  • Now the console stays open, but doesn't output the copied text... Maybe there is another error in it how I implemented the SharpClipboard function.. – Patrick Grebe Jan 20 '21 at 08:12

2 Answers2

1

Did it with the following code:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

//https://stackoverflow.com/questions/621577/clipboard-event-c-sharp
//https://stackoverflow.com/questions/17762037/error-while-trying-to-copy-string-to-clipboard
//https://gist.github.com/glombard/7986317

internal static class NativeMethods
{
    //Reference https://learn.microsoft.com/en-us/windows/desktop/dataxchg/wm-clipboardupdate
    public const int WM_CLIPBOARDUPDATE = 0x031D;
    //Reference https://www.pinvoke.net/default.aspx/Constants.HWND
    public static IntPtr HWND_MESSAGE = new IntPtr(-3);

    //Reference https://www.pinvoke.net/default.aspx/user32/AddClipboardFormatListener.html
    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool AddClipboardFormatListener(IntPtr hwnd);

    //Reference https://www.pinvoke.net/default.aspx/user32.setparent
    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    //Reference https://www.pinvoke.net/default.aspx/user32/getwindowtext.html
    [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

    //Reference https://www.pinvoke.net/default.aspx/user32.getwindowtextlength
    [DllImport("user32.dll")]
    public static extern int GetWindowTextLength(IntPtr hWnd);

    //Reference https://www.pinvoke.net/default.aspx/user32.getforegroundwindow
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
}

public static class Clipboard
{
    public static string GetText()
    {
        string ReturnValue = string.Empty;
        Thread STAThread = new Thread(
            delegate ()
            {
                // Use a fully qualified name for Clipboard otherwise it
                // will end up calling itself.
                ReturnValue = System.Windows.Forms.Clipboard.GetText();
            });
        STAThread.SetApartmentState(ApartmentState.STA);
        STAThread.Start();
        STAThread.Join();

        return ReturnValue;
    }
}

public sealed class ClipboardNotification
{
    private class NotificationForm : Form
    {
        public NotificationForm()
        {
            //Turn the child window into a message-only window (refer to Microsoft docs)
            NativeMethods.SetParent(Handle, NativeMethods.HWND_MESSAGE);
            //Place window in the system-maintained clipboard format listener list
            NativeMethods.AddClipboardFormatListener(Handle);
        }

        protected override void WndProc(ref Message m)
        {
            //Listen for operating system messages
            if (m.Msg == NativeMethods.WM_CLIPBOARDUPDATE)
            {
                //Get the date and time for the current moment expressed as coordinated universal time (UTC).
                DateTime saveUtcNow = DateTime.UtcNow;
                Console.WriteLine("Copy event detected at {0} (UTC)!", saveUtcNow);

                //Write to stdout active window
                IntPtr active_window = NativeMethods.GetForegroundWindow();
                int length = NativeMethods.GetWindowTextLength(active_window);
                StringBuilder sb = new StringBuilder(length + 1);
                NativeMethods.GetWindowText(active_window, sb, sb.Capacity);
                Console.WriteLine("Clipboard Active Window: " + sb.ToString());

                //Write to stdout clipboard contents
                Console.WriteLine("Clipboard Content: " + Clipboard.GetText());
            }
            //Called for any unhandled messages
            base.WndProc(ref m);
        }
    }

    private static void Main(string[] args)
    {
        //starts a message loop on current thread and displays specified form
        Application.Run(new NotificationForm());
    }
}
Patrick Grebe
  • 111
  • 2
  • 14
1

Your code works, it doesn't output anything because it's debug.writeline, so the output is in the debug window of visual studio. Use console.writeline instead.

gshep
  • 50
  • 5