最近写的一个程序,需要一个目录下的程序只能运行一次,运行多次时,如果是带参数运行,就将参数传给已经运行的程序.传参数我会的只有两种办法1.使用文件的监视,也就是System.IO.FileSystemWatcher,程序在启动时发现已有实例在运行,则将传的参数序列化后保存在一个目录,而那个运行着的程序会检测到有文件产生,则读取进行操作.2.使用windows消息,也就是程序启动时发现有实例已在运行,就将接参数整理成string,然后传给运行着的程序,主要代码如下.
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;namespace Speeding.Util
{
//WM_COPYDATA消息所要求的数据结构
public struct CopyDataStruct
{
public IntPtr dwData;
public int cbData; [MarshalAs(UnmanagedType.LPStr)]
public string lpData;
} /// <summary>
/// 本类封装了一些进程间通讯的细节
/// </summary>
public class WinMessageUtil
{
public const int WM_COPYDATA = 0x004A; //通过窗口的标题来查找窗口的句柄
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern int FindWindow(string lpClassName, string lpWindowName); //在DLL库中的发送消息函数
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage
(
int hWnd, // 目标窗口的句柄
int Msg, // 在这里是WM_COPYDATA
int wParam, // 第一个消息参数
ref CopyDataStruct lParam // 第二个消息参数
); /// <summary>
/// 发送消息,只能传递一个自定义的消息ID和消息字符串,想传一个结构,但没成功
/// </summary>
/// <param name="destProcessName">目标进程名称,如果有多个,则给每个都发送</param>
/// <param name="msgID">自定义数据,可以通过这个来决定如何解析下面的strMsg</param>
/// <param name="strMsg">传递的消息,是一个字符串</param>
public static void SendMessage(string destProcessPath, int msgID, string strMsg)
{
if (strMsg == null)
return;
string destProcessName = System.IO.Path.GetFileName(destProcessPath);
//按进程名称查找,同名称的进程可能有许多,所以返回的是一个数组
Process[] foundProcess = Process.GetProcessesByName(destProcessName);
foreach (Process p in foundProcess)
{
int toWindowHandler = p.MainWindowHandle.ToInt32();
if (toWindowHandler != 0)
{
CopyDataStruct cds;
cds.dwData = (IntPtr)msgID; //这里可以传入一些自定义的数据,但只能是4字节整数
cds.lpData = strMsg; //消息字符串
cds.cbData = System.Text.Encoding.Default.GetBytes(strMsg).Length + 1; //注意,这里的长度是按字节来算的 //发送方的窗口的句柄, 由于本系统中的接收方不关心是该消息是从哪个窗口发出的,所以就直接填0了
int fromWindowHandler = 0;
SendMessage(toWindowHandler, WM_COPYDATA, fromWindowHandler, ref cds);
}
}
} /// <summary>
/// 接收消息,得到消息字符串
/// </summary>
/// <param name="m">System.Windows.Forms.Message m</param>
/// <returns>接收到的消息字符串</returns>
public static string ReceiveMessage(ref System.Windows.Forms.Message m)
{
CopyDataStruct cds = (CopyDataStruct)m.GetLParam(typeof(CopyDataStruct));
return cds.lpData;
}
}
}
请问大家,用哪种方案比较好,不影响主程序的运行
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;namespace Speeding.Util
{
//WM_COPYDATA消息所要求的数据结构
public struct CopyDataStruct
{
public IntPtr dwData;
public int cbData; [MarshalAs(UnmanagedType.LPStr)]
public string lpData;
} /// <summary>
/// 本类封装了一些进程间通讯的细节
/// </summary>
public class WinMessageUtil
{
public const int WM_COPYDATA = 0x004A; //通过窗口的标题来查找窗口的句柄
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern int FindWindow(string lpClassName, string lpWindowName); //在DLL库中的发送消息函数
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage
(
int hWnd, // 目标窗口的句柄
int Msg, // 在这里是WM_COPYDATA
int wParam, // 第一个消息参数
ref CopyDataStruct lParam // 第二个消息参数
); /// <summary>
/// 发送消息,只能传递一个自定义的消息ID和消息字符串,想传一个结构,但没成功
/// </summary>
/// <param name="destProcessName">目标进程名称,如果有多个,则给每个都发送</param>
/// <param name="msgID">自定义数据,可以通过这个来决定如何解析下面的strMsg</param>
/// <param name="strMsg">传递的消息,是一个字符串</param>
public static void SendMessage(string destProcessPath, int msgID, string strMsg)
{
if (strMsg == null)
return;
string destProcessName = System.IO.Path.GetFileName(destProcessPath);
//按进程名称查找,同名称的进程可能有许多,所以返回的是一个数组
Process[] foundProcess = Process.GetProcessesByName(destProcessName);
foreach (Process p in foundProcess)
{
int toWindowHandler = p.MainWindowHandle.ToInt32();
if (toWindowHandler != 0)
{
CopyDataStruct cds;
cds.dwData = (IntPtr)msgID; //这里可以传入一些自定义的数据,但只能是4字节整数
cds.lpData = strMsg; //消息字符串
cds.cbData = System.Text.Encoding.Default.GetBytes(strMsg).Length + 1; //注意,这里的长度是按字节来算的 //发送方的窗口的句柄, 由于本系统中的接收方不关心是该消息是从哪个窗口发出的,所以就直接填0了
int fromWindowHandler = 0;
SendMessage(toWindowHandler, WM_COPYDATA, fromWindowHandler, ref cds);
}
}
} /// <summary>
/// 接收消息,得到消息字符串
/// </summary>
/// <param name="m">System.Windows.Forms.Message m</param>
/// <returns>接收到的消息字符串</returns>
public static string ReceiveMessage(ref System.Windows.Forms.Message m)
{
CopyDataStruct cds = (CopyDataStruct)m.GetLParam(typeof(CopyDataStruct));
return cds.lpData;
}
}
}
请问大家,用哪种方案比较好,不影响主程序的运行
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;namespace WindowsFormsApplication13
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary> [DllImport("User32")]
static extern int SendMessage(IntPtr Handle, int Msg, int WParam, int LParam);
[STAThread]
static void Main()
{
foreach (Process P in Process.GetProcesses())
if (P.ProcessName == "WindowsFormsApplication13") //直接运行exe
if (P.MainWindowHandle.ToInt32() > 0)
{
SendMessage(P.MainWindowHandle, 0x8888, 0, 0);
return;
} Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace WindowsFormsApplication13
{
public partial class Form1 : Form
{
public String Info = "Info"; public Form1()
{
InitializeComponent();
} protected override void WndProc(ref Message m)
{
if (m.Msg == 0x8888)
{
Form F = (Form)Form.FromHandle(m.HWnd); MessageBox.Show(F.GetType().GetField("Info").GetValue(F).ToString());
}
else
base.WndProc(ref m);
}
}
}
static void Main(string[] args)
{
bool created;
Mutex m = new Mutex(true, "test", out created);
if (created)
{
Console.WriteLine("first run...");
Console.WriteLine("press any key to exit...");
Console.ReadKey();
}
else
{
Console.WriteLine("now running,args:");
foreach (var item in args)
{
Console.WriteLine(item);
}
}
}
至于为什么不能用Form.FromHandle见这一贴3楼的解释:http://topic.csdn.net/u/20081221/01/457bb3b1-2f19-47e2-9621-cf4117ee45ce.html你代码中Form F = (Form)Form.FromHandle(m.HWnd);中的m.HWnd是接收窗口的句柄。
LZ是希望新进程把自己的参数传给已经启动的进程.