I have this line of code:
System.Drawing.Icon icon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
A few lines later, after icon is used I have the line:
Win32.DestroyIcon(shinfo.hIcon);
However when running a static analysis on my code it says there is a potential for Resource_Leak from icon. I am wondering will it make any difference if I call the dispose method:
icon.Dispose();
rather than the Win32.DestroyIcon() that is being used right now. Is there any difference between them? I am just maintaining this code so I am not sure if there was any special intnetion by the original developer to use Win32.DestroyIcon.
The static analysis is triggering because you aren't disposing the "IDisposable resource".
I would recommend sticking to the managed version throughout, and using icon.Dispose(). This will (internally) take care of calling DestroyIcon for you, but stick to the pure managed API throughout.
Win32.DestroyIcon is really intended more for use with icons you're receiving as an IntPtr, not for use with an Icon instance that is managed by the framework entirely.
I have had NO END of grief in this area - I've been trying to animate a form's icon (and consequently the one in the task bar) without it leaking resources.
When I disposed of the icon (as suggested on MSDN) resources leaked, when I used "DestroyIcon" all subsequent updates failed. This code below shows everything in the correct order.
API Declaration:
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);
FINALLY the solution:
IntPtr iconHandle = dynamicBitmap.GetHicon();
Icon tempManagedRes = Icon.FromHandle(iconHandle);
this.Icon = (Icon)tempManagedRes.Clone();
tempManagedRes.Dispose();
DestroyIcon(iconHandle);
Also posted in this question:
Icon.FromHandle: should I Dispose it, or call DestroyIcon?
Related
After reading quite a bit on the clipboard being blocked when trying to use it, I tried using OpenClipboard() directly, to capture the clipboard and be able to use it from my window.
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
[DllImport("user32.dll", SetLastError=true)]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", SetLastError=true)]
private static extern bool CloseClipboard();
private int idx = 0;
private void refresh_Tick(object sender, EventArgs e) {
switch (idx++) {
case 0:
OpenClipboard(Handle);
break;
default:
Clipboard.SetText(" ");
break;
}
}
}
When using SetText, I will get the infamous error:
A first chance exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Windows.Forms.dll
Additional information: Requested Clipboard operation did not succeed.
So, the questions:
Does OpenClipboard() actually work?
What is the argument for OpenClipboard() for? The rest of the API does not need a handle to any window, so why does OpenClipboard()? In other words, the Clipboard is supposed to be shared between PROCESSES, not WINDOWS - but I don't see a way to lock it for my current process.
I can call OpenClipboard(IntPtr.Zero), which MSDN says:
If this parameter is NULL, the open clipboard is associated with the current task.
What is 'task' supposed to mean?
Does OpenClipboard() actually work?
OpenClipboard() works, but definitely not in the way you showed. It is a raw Win32 API. Here is an example of using it to copy string to clipboard (C/C++).
What is the argument for OpenClipboard() for?
To be honest, I'm not sure about this. Usually we just pass NULL aka IntPtr.Zero and let it associate with the current task. I guess it retrieves the thread that created the specified window, and then associates it with the clipboard.
What is task? Well here is my understanding. Back in Win16 days, instead of 'Thread' or 'Process', they used the terminology 'Task'. There was a function to GetCurrentTask().
Then the function is replaced by GetCurrentProcess() and GetCurrentThread().
Since it makes more sense that only one thread can access a shared resource at one time, I would say that 'Task' actually means 'Thread'.
The rest of the API does not need a handle to any window, so why does OpenClipboard()?
If my assumption above is correct, that is, only one thread can access Clipboard at a time, then chances are, Windows will use the thread/window you specified with OpenClipboard() previously, until you call CloseClipboard() or the thread/window becomes invalid. That's why you don't need to specify the HWND all the time.
In other words, the Clipboard is supposed to be shared between PROCESSES, not WINDOWS - but I don't see a way to lock it for my current process.
It locks, though I'm not sure about C# P/Invoke. If you have access to Win32/C development toolkit, compile and run the following code:
#include <conio.h>
#include <Windows.h>
int main()
{
OpenClipboard(GetForegroundWindow());
_getch();
return 0;
}
And see what happen if you use Clipboard in other program. :) Close the console window to restore.
I use Win32 SHGetFileInfo to get a handle to the icon belonging to a certain file. There are a lot of descriptions how to do this, also on stackoverflow, for instance: Get icons used by shell
After calling the function you have a struct with the handle to the Icon. Using the static method Icon.FromHandle I can convert it to an object of class System.Drawing.Icon. This class implements System.IDisposable. Proper usage would be like:
using (Icon icon = Icon.FromHandle(shFileInfo.hIcon))
{
// do what you need to do with the icon
}
Upon leaving the using statement the icon object is disposed.
MSDN warns in the description of Icon.FromHandle (click to view):
When using this method, you must dispose of the original icon by using the DestroyIcon method in the Win32 API to ensure that the resources are released.
And in Icon.Dispose (click to view)
Releases all resources used by this Icon.
Question:
Is it enough to Dispose() the object, or should I call both Dispose() and DestroyIcon, or maybe call DestroyIcon instead of Disposing the object?
The .NET Icon class is remarkably clumsy, taking care of this yourself is required. The MSDN article for SHFILEICON makes no bones about it, you must call DestroyIcon(). And so does the MSDN article for Icon.FromHandle(). The exact moment in time you call DestroyIcon matters a great deal as well, it must be delayed until some code either has made a copy of the icon or until you no longer need the icon and would normally call its Dispose() method.
Beware of the code snippet in the MSDN article, it shows a scenario where DestroyIcon() is called early. Okay in that specific case since it is assigned to the Form.Icon property. A corner case and surely not what you want to do.
The only really decent way to deal with this is to override the behavior of Icon.FromHandle() and force the object to take ownership of the native icon handle. So that it will automatically call DestroyIcon() when you dispose it. That requires a hack, the Icon constructor that lets you do this is internal. Reflection to the rescue, you can use the code from this post, note the GetConstructor() call. Start feeling good about it by writing a little unit test that does this a million times. If you hate it then write your own IDisposable wrapper so you can both dispose the icon and pinvoke DestroyIcon().
Addition by OP. There is an error in this answer. Because of all the comments it became harsh to see the forest through the trees. Hence I decided to edit this answer. (Sorry if I offended someone)
The .net source code is online: http://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Icon.cs,81a28d20524554ae
Take a look at Icon.FromHandle:
public static Icon FromHandle(IntPtr handle)
{
IntSecurity.ObjectFromWin32Handle.Demand();
return new Icon(handle);
}
internal Icon(IntPtr handle) : this(handle, false)
{
}
internal Icon(IntPtr handle, bool takeOwnership)
{
if (handle == IntPtr.Zero)
{
throw new ArgumentException(SR.GetString(SR.InvalidGDIHandle,
(typeof(Icon)).Name));
}
this.handle = handle;
this.ownHandle = takeOwnership;
}
Note that after Icon.FromHandle ownHandle is false.
Let's look at Dispose:
void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
DestroyHandle();
}
}
internal void DestroyHandle()
{
if (ownHandle)
{
SafeNativeMethods.DestroyIcon(new HandleRef(this, handle));
handle = IntPtr.Zero;
}
}
Conclusion: After Icon.FromHandle, the field ownHandle is false, and thus Dispose / FromHandle won't call DestroyIcon
Therefore: if you create an Icon using Icon.FromHandle you'll have to Dispose() the Icon as well as call DestroyIcon, just as the remarks section says
I have had NO END of grief in this area - I've been trying to animate a form's icon (and consequently the one in the task bar) without it leaking resources.
When I disposed of the icon (as suggested on MSDN) resources leaked, when I used "DestroyIcon" all subsequent updates failed. This code below shows everything in the correct order.
API Declaration:
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);
FINALLY the solution:
IntPtr iconHandle = dynamicBitmap.GetHicon();
Icon tempManagedRes = Icon.FromHandle(iconHandle);
this.Icon = (Icon)tempManagedRes.Clone();
tempManagedRes.Dispose();
DestroyIcon(iconHandle);
Also posted in this question:
Win32.DestroyIcon vs. Icon.Dispose
I tested a lot. But I found no disadvantages of those 2!
But see the accepted answer.
I read here that calling GetLastError in managed code is unsafe because the Framework might internally "overwrite" the last error. I have never had any noticeable problems with GetLastError and it seems for me that the .NET Framework is smart enough not to overwrite it. Therefore I have a few questions on that topic:
in [DllImport("kernel32.dll", SetLastError = true)] does the SetLastError attribute make the Framework store the error code for the use of Marshal.GetLastWin32Error() ?
is there an example where plain GetLastError fails to give the correct result ?
do I really HAVE to use Marshal.GetLastWin32Error() ?
is this "problem" Framework version related ?
public class ForceFailure
{
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);
public static void Main()
{
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
System.Console.WriteLine("It worked???");
else
{
// the first last error check is fine here:
System.Console.WriteLine(GetLastError());
System.Console.WriteLine(Marshal.GetLastWin32Error());
}
}
}
Producing errors:
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
Console.WriteLine("It worked???");
else
{
// bad programming but ok GetlLastError is overwritten:
Console.WriteLine(Marshal.GetLastWin32Error());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
}
catch { }
Console.WriteLine(GetLastError());
}
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
Console.WriteLine("It worked???");
else
{
// bad programming and Marshal.GetLastWin32Error() is overwritten as well:
Console.WriteLine(GetLastError());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
}
catch { }
Console.WriteLine(Marshal.GetLastWin32Error());
}
// turn off concurrent GC
GC.Collect(); // doesn't effect any of the candidates
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(Marshal.GetLastWin32Error());
Console.WriteLine(Marshal.GetLastWin32Error());
// when you exchange them -> same behaviour just turned around
I don't see any difference! Both behave the same except Marshal.GetLastWin32Error stores results from App->CLR->WinApi calls as well and GetLastError stores only results from App->WinApi calls.
Garbage Collection seems not to call any WinApi functions overwriting the last error code
GetLastError is thread-safe. SetLastError stores an error code for each thread calling it.
since when would GC run in my threads ?
You must always use the Marshal.GetLastWin32Error. The main problem is the garbage collector. If it runs between the call of SetVolumeLabel and the call of GetLastError then you will receive the wrong value, because the GC has surely overwritten the last result.
Therefore you always need to specify the SetLastError=true in the DllImport-Attribute:
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);
This ensures that the marhsallling stub calls immediately after the native function the "GetLastError" and stores it in the local thread.
And if you have specified this attribute then the call to Marshal.GetLastWin32Error will always have the correct value.
For more info see also "GetLastError and managed code" by Adam Nathan.
Also other function from .NET can change the windows "GetLastError". Here is an example which produces different results:
using System.IO;
using System.Runtime.InteropServices;
public class ForceFailure
{
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);
public static void Main()
{
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
System.Console.WriteLine("It worked???");
else
{
System.Console.WriteLine(Marshal.GetLastWin32Error());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) {}
}
catch
{
}
System.Console.WriteLine(GetLastError());
}
}
}
Also it seems that this is depended on the CLR which you are using! If you compile this with .NET2, it will produce "2 / 0"; if you switch to .NET 4, it will output "2 / 2"...
So it is depended on the CLR version, but you should not trust the native GetLastError function; always use the Marshal.GetLastWin32Error.
TL;DR
Do use [DllImport(SetLastError = true)] and Marshal.GetLastWin32Error()
perform the Marshal.GetLastWin32Error() immediately after a failing Win32 call and on the same thread.
Argumentation
As i read it, the official explanation why you need Marshal.GetLastWin32Error can be found here:
The common language runtime can make internal calls to APIs that overwrite the GetLastError maintained by the operating system.
To say it in other words:
Between your Win32 call which sets the error, the CLR may "insert" other Win32 calls which could overwrite the error.
Specifying [DllImport(SetLastError = true)] makes sure that the CLR retrieves the error code before the CLR executes any unexpected Win32 calls.
To access that variable we need to use Marshal.GetLastWin32Error.
Now what #Bitterblue found is that these "inserted calls" don't happen often - he couldn't find any. But that's not really surpising. Why? Because it's extremely difficult to "black box test" whether GetLastError works reliably:
you can detect unreliability only if a CLR-inserted Win32 call actually fails in the meantime.
failure of these calls may be dependent on internal/external factors. Such as time/timing, memory pressure, devices, state of computer, windows version...
insertion of Win32 calls by CLR may be dependent on external factors. So under some circumstances the CLR inserts a Win32 call, under others it doesn't.
behavior can change with different CLR versions as well
There's is one specific component - the Garbage collector (GC) - which is known to interrupt a .net thread if there's memory pressure and do some processing on that thread (see What happens during a garbage collection). Now if the GC were to execute a failing Win32 call, this would break your call to GetLastError.
To sum it up, you have a plethora of unknown factors which can influence the reliability of GetLastError. You'll most likely not find an unreliability problem when developing/testing, but it might blow up in production at any time. So do use [DllImport(SetLastError = true)] and Marshal.GetLastWin32Error() and improve your sleep quality ;-)
in [DllImport("kernel32.dll", SetLastError = true)] does the SetLastError attribute make the Framework store the error code for the use of Marshal.GetLastWin32Error() ?
Yes, as is documented in DllImportAttribute.SetLastError Field
is there an example where plain GetLastError fails to give the correct result ?
As documented in Marshal.GetLastWin32Error Method, if the framework itself (e.g. the garbage collector) calls any native method that sets an error value between your calls to the native method and GetLastError you would get the error value of the framework's call instead of your call.
do I really HAVE to use Marshal.GetLastWin32Error() ?
Since you can't ensure that the framework will never call a native method between your call and the call to GetLastError, yes. Also, why not?
is this "problem" Framework version related ?
It could definitely be (e.g. changes in the garbage collector), but it doesn't have to.
Can someone tell me how to get the handle of a Windows console application in C#? In a Windows Forms application, I would normally try this.Handle.
Not sure it works, but you can try that :
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
The aforementioned Process.MainWindowHandle method only works for the process that started the console
The FindWindowByCaption method is inherently unreliable
Here's a robust way to do this:
The related functions from the Console Win32 API are:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
static extern bool FreeConsole();
For the console the current process is attached to, just GetConsoleWindow() is enough
For the console another process is attached to, attach to it as well with AttachConsole, call GetConsoleWindow, them immediately detach with FreeConsole.
For the extra cautious, register a console event handler before attaching (and unregister it after detaching) as well so you don't accidentally get terminated if a console event happens in the tiny time frame you're attached to the console:
[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine,
bool Add);
delegate Boolean ConsoleCtrlDelegate(CtrlTypes CtrlType);
enum CtrlTypes : uint {
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
bool is_attached=false;
ConsoleCtrlDelegate ConsoleCtrlDelegateDetach = delegate(CtrlType) {
if (is_attached = !FreeConsole())
Trace.Error('FreeConsole on ' + CtrlType + ': ' + new Win32Exception());
return true;
};
Making changes to the current process just to read something is rather ugly (when this is a console process, this gets really ugly since it requires a helper process to avoid terminating the current console). Nevertheless, further investigation shows that there's no other way short of injecting into the csrss process or the target process.
Console correspondence information is located in and managed by csrss.exe (or a multitude of those, one for each session, since Vista), so it can't be retrieved with the likes of ReadProcessMemory. All that csrss exposes is the CSRSS LPC API. There's only one relevant function in the full API list, SrvGetConsoleWindow. And it doesn't accept a PID but determines that of the calling party as seen in an alternative implementation or the function's disassembly in winsrv.dll.
Try this:
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
public static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName);
…
Console.Title = "Test";
…
IntPtr handle = FindWindowByCaption(IntPtr.Zero, Console.Title);
I've just solved this problem for myself (unfortunately before seeing Thomas's answer which is much quicker). Well, here's another way for those who are not satisfied with his answer. I'm writing this answer because I want to provide another answer + a better way to design the Program class if you're treating your console as a Window. Let's begin with that design:
I've kind of changed the default style of the Program class. I've actually made it into a class that has a program in it, and not just one method which represent it and uses other classes for content. (If you don't know what I mean, not important).
The reason I had to do it is because I wanted to write the following event handler:
private void CatchUnhandled(Object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
MessageBox.Show(this, exception.Message, "Error"); // Check out 1st arg.
}
It overloads this method MessageBox.Show(IWin32Window, String, String).
Because Console doesn't implement IWin32Window, I had to implement it myself, of course, in order to just call this in the 1st argument.
Here is the implementation of it and everything else:
Note: this code is copy-pasted from my application, you can feel free to change the access modifiers
Program Class Declaration:
internal class Program : IWin32Window
{
...
}
IWin32Window Implementation:
public IntPtr Handle
{
get { return NativeMethods.GetConsoleWindow(); }
}
It uses the following class:
internal static class NativeMethods
{
[DllImport("kernel32.dll")]
internal static extern IntPtr GetConsoleWindow();
}
Now, the problem is that you can't actually call this in Main, being a static method, so whatever was in Main I've moved to a new method named Start and all Main is doing is creating a new Program and calling Start.
private static void Main()
{
new Program().Start();
}
private void Start()
{
AppDomain.CurrentDomain.UnhandledException += CatchUnhandled;
throw new Exception();
}
The result was, of course, a message-box with my console's window as an owner.
Using this method for a message-box, is of course only one application of this method.
I don't think there is such a thing. The console window is not accessible to the application. You MIGHT try to iterate the process list looking for your own process name. The Process class IIRC contains a property for the program's main window handle, which might be the console window for console applications - which I'm not sure of.
One more version in VB.Net on how to show MessageBox on top of console window
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Friend Module NativeMethods
<DllImport("kernel32.dll")> Friend Function GetConsoleWindow() As IntPtr
End Function
End Module
NotInheritable Class WndProxy
Implements IWin32Window
ReadOnly Property Handle As IntPtr Implements IWin32Window.Handle
Sub New(_hwnd As IntPtr)
Handle = _hwnd
End Sub
End Class
Module Module1
Sub Main()
' using MainWindowHandle
Dim w = New WndProxy(Process.GetCurrentProcess().MainWindowHandle)
MessageBox.Show(w, "Hi")
' using GetConsoleWindow api
Dim s = New WndProxy(NativeMethods.GetConsoleWindow)
MessageBox.Show(s, "Hi")
End Sub
End Module
In a console application which streamed diagostics to the console, and for which I wanted to disable mouse input, I tried
GetConsoleWindow(),
Process.GetCurrentProcess().MainWindowHandle, and FindWindowByCaption(IntPtr.Zero, Console.Title).
Each of these returned the same non-zero handle, but when I tried to use that handle in SetConsoleMode it threw a "Invalid Handle" exception. Finally I tried SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode | ENABLE_EXTENDED_FLAGS)) with STD_INPUT_HANDLE defined as -10, and it worked. MS's documentation suggests that handles to consoles may be reassigned, and I am not comfortable or happy with this solution, but so far it is the only thing I've found that allows me to disable quick edit mode programmatically. GetStdHandle(STD_INPUT_HANDLE) returns '3', the other calls return a 7 digit value that varies each time the program is run.
The following code implements a simple singleton that ensures only 1 instance of my application can be run. However, if another instance is started, I need to be able to grab that instance's command-line arguments, pass them to the initial instance, then terminate the second instance.
The issue comes in when I'm attempting to get hold of the first instance of the application. Once I've found the handle of that instance's main form, I pass it to the Control.FromHandle() method, expecting to get back a MainForm. Instead, the return value is always null. (Control.FromChildHandle() gives the same result.)
Therefore, my question is simply: what am I doing wrong? And is this even possible in .NET?
public class MainForm : Form
{
[DllImport("user32")]
extern static int ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32")]
extern static bool SetForegroundWindow(IntPtr hWnd);
private Mutex singletonMutex;
private void MainForm_Load(object sender, EventArgs e)
{
bool wasCreated;
singletonMutex = new Mutex(false, Application.ProductName + "Mutex", out wasCreated);
// returns false for every instance except the first
if (!wasCreated)
{
Process thisProcess = Process.GetCurrentProcess();
Process[] peerProcesses = Process.GetProcessesByName(thisProcess.ProcessName.Replace(".vshost", string.Empty));
foreach (Process currentProcess in peerProcesses)
{
if (currentProcess.Handle != thisProcess.Handle)
{
ShowWindowAsync(currentProcess.MainWindowHandle, 1); // SW_NORMAL
SetForegroundWindow(currentProcess.MainWindowHandle);
// always returns null !!!
MainForm runningForm = (MainForm) Control.FromHandle(currentProcess.MainWindowHandle);
if (runningForm != null)
{
runningForm.Arguments = this.Arguments;
runningForm.ProcessArguments();
}
break;
}
}
Application.Exit();
return;
}
}
Single-instance apps are well supported by the .NET framework. Check this thread for an example that does exactly what you need.
Control.FromHandle isn't going to work because the control you're looking for is in another process (and therefore in another appdomain).
You already have the WindowHandle but it's use is limited to the Win32 API. Nothing from WinForms is going to work.
You can send (WM_) messages but it's hard to get data across.
Options
use something low-level with a
temp-file.
use remoting (WCF)
Try the following
var form = (Form)(Control.FromHandle(myHandle));
EDIT
Re-read your question and realized you are looking at a handle in another process. There is no way to convert a handle in another process to a Form instance in the current process. My solution will only work for handles in the same process.
The only way to get ahold of the Form instance is to use Remoting. But that will require cooperation on the part of both processes which does not appear to be what you are looking for.
You are really trying to implement a singleton application. There are a few examples in the Internet (sorry, haven't really tried myself), e.g.
http://www.codeproject.com/KB/cs/SingletonApplication.aspx
http://www.nathanm.com/csharp-wpf-singleton-application/
You can't call code in another process directly, you need to use some form of inter-process communication
If you are communication only between processes started by the same user on the same computer you can use window messages (using WinAPI PostMessage and overriding WndProc), otherwise I think remoting is the easiest to use in .net
I use the Microsoft.VisualBasic.dll library described in the thread that nobugz pointed to. Yes, you can use it in C#. You just override the OnStartupNextInstance and pass the command line into your program in whatever way works best for you.
This is a whole lot easier than messing around with the threads manually.