我有一个 WinForms 应用程序,如果已经有一个实例正在运行并且用户试图启动另一个实例,我会在调用 Application.Run() 之前通过检查 Mutex 来停止它。那部分工作得很好。我想做的是在终止新进程之前将一条消息从应用程序的新实例(以及一条字符串形式的数据)传递到现有实例。
我已经尝试调用 PostMessage,并且确实在正在运行的应用程序上收到了消息,但是我在 lparam 中传递的字符串失败(是的,我已经检查以确保我传递了一个好的字符串开始) . 我怎样才能最好地做到这一点?
static class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PostMessage(int hhwnd, uint msg, IntPtr wparam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
private const int HWND_BROADCAST = 0xffff;
static uint _wmJLPC = unchecked((uint)-1);
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
_wmJLPC = RegisterWindowMessage("JumpListProjectClicked");
if (_wmJLPC == 0)
{
throw new Exception(string.Format("Error registering window message: \"{0}\"", Marshal.GetLastWin32Error().ToString()));
}
bool onlyInstance = false;
Mutex mutex = new Mutex(true, "b73fd756-ac15-49c4-8a9a-45e1c2488599_ProjectTracker", out onlyInstance);
if (!onlyInstance) {
ProcessArguments();
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
GC.KeepAlive(mutex);
}
internal static void ProcessArguments()
{
if (Environment.GetCommandLineArgs().Length > 1)
{
IntPtr param = Marshal.StringToHGlobalAuto(Environment.GetCommandLineArgs()[1]);
PostMessage(HWND_BROADCAST, _wmJLPC, IntPtr.Zero, param);
}
}
}
在其他地方,以我的形式...
protected override void WndProc(ref Message m)
{
try
{
if (m.Msg == _wmJLPC)
{
// always returns an empty string
string param = Marshal.PtrToStringAnsi(m.LParam);
// UI code omitted
}
}
catch (Exception ex)
{
HandleException(ex);
}
base.WndProc(ref m);
}