I Wrote a short program in C# that monitors the clipboard. When a certain string enters the clipboard, a program must be opened with Process.Start (depending on the string). Everything works fine, but sometimes the application is being opened twice. I Don't know why this is happening.
namespace ClipboardMonitor {
public class Form1 : System.Windows.Forms.Form {
[DllImport("User32.dll")]
protected static extern int SetClipboardViewer(int hWndNewViewer);
[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
const int SW_SHOW = 5;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
IntPtr nextClipboardViewer;
private System.ComponentModel.Container components = null;
public Form1() {
InitializeComponent();
nextClipboardViewer = (IntPtr)SetClipboardViewer((int) this.Handle);
var handle = GetConsoleWindow();
ShowWindow(handle, SW_HIDE);
}
protected override void Dispose( bool disposing ) {
ChangeClipboardChain(this.Handle, nextClipboardViewer);
if( disposing ) {
if (components != null) {
components.Dispose();
}
}
base.Dispose( disposing );
}
private void InitializeComponent() {
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
this.Name = "Form1";
}
[STAThread]
static void Main() {
Application.Run(new Form1());
}
protected override void WndProc(ref System.Windows.Forms.Message m) {
const int WM_DRAWCLIPBOARD = 0x308;
const int WM_CHANGECBCHAIN = 0x030D;
switch(m.Msg) {
case WM_DRAWCLIPBOARD:
DisplayClipboardData();
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
break;
case WM_CHANGECBCHAIN:
if (m.WParam == nextClipboardViewer)
nextClipboardViewer = m.LParam;
else
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
break;
default:
base.WndProc(ref m);
break;
}
}
void DisplayClipboardData() {
Thread.Sleep(500);
try {
IDataObject iData = new DataObject();
iData = Clipboard.GetDataObject();
if (iData.GetDataPresent(DataFormats.Text)) {
string path = iData.GetData(DataFormats.Text).ToString();
string[] words = path.Split('_');
if (words[0] == "startLO") {
ProcessStartInfo info = new ProcessStartInfo(words[1]);
Process p = Process.Start(info);
}
} else {
// We doen niets.
}
}
catch(Exception e) {
MessageBox.Show(e.ToString());
}
}
}
One explanation would be that there are multiple clipboard events happening in rapid succession. This is fairly common. You can defend against this with a "settle time" delay. i.e. instead of reacting right away, set a timer or create a thread to handle it "in a little while". As more events come in, keep deferring the settletime. when the settletime finally expires, the timer or thread is allowed to actually run your program.