C#中如何在main函数中实现单例模式
我描述可能不是那么准确。。
现在我们要实现在命令行多次执行某一程序时,该程序只会执行出现一次,每次运行的不同结果会以选项卡的形式出现在程序窗口中,就像这样
目前我已经可以做到识别出是否是第一次运行该程序,但不会实现每当再运行一次该程序时,如何动态添加一个tabpage,(通过button什么的添加我会,但是直接在运行程序的时候就自动添加我不太会)...
谢谢大家
[解决办法]
interface IRemoteApplicationInterface
{
void RemoteApplicationNotification();
}
class RemotableApplication : MarshalByRefObject, IRemoteApplicationInterface
{
/// <summary>
/// Start for remote application notification.
/// </summary>
/// <param name="name">remote name.</param>
/// <param name="action">remote notification action.</param>
public static void RemoteApplicationNotification(string name, Action action)
{
System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(new System.Runtime.Remoting.Channels.Ipc.IpcChannel(name + ".IPC"), false);
System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotableApplication), "Launch", System.Runtime.Remoting.WellKnownObjectMode.SingleCall);
System.Diagnostics.Debug.Assert(remoteApplicationNotificationAction == null);
remoteApplicationNotificationAction = action;
}
/// <summary>
/// call the running application to do...
/// </summary>
/// <param name="name">remote name.</param>
public static void NotificationRemoteApplication(string name)
{
var ra = Activator.GetObject(typeof(IRemoteApplicationInterface), "ipc://" + name + ".IPC/Launch") as IRemoteApplicationInterface;
if (ra != null)
{
ra.RemoteApplicationNotification();
}
}
#region IRemoteApplicationInterface 成员
static Action remoteApplicationNotificationAction = null;
void IRemoteApplicationInterface.RemoteApplicationNotification()
{
if (remoteApplicationNotificationAction != null)
{
remoteApplicationNotificationAction();
}
}
#endregion
}
static class UniqueEntry
{
public static void Run(string name, Action run, Action notification, Func<bool> notify)
{
bool created;
string mname = Environment.UserName + "." + name;
var mutex = new System.Threading.Mutex(true, @"Local\" + mname, out created);
if (!created)
{ // 程序在运行中。
if (notify())
{
try
{
RemotableApplication.NotificationRemoteApplication(mname);
}
catch
{
}
}
return;
}
else
{
try
{
RemotableApplication.RemoteApplicationNotification(mname, notification);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
return;
}
}
run();
System.GC.KeepAlive(mutex);
}
}
/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
static void Main(string[] args)
{
AShura.Windows.Helpers.UniqueEntry.Run("myname", () =>
{
try
{
App app = new App();
app.InitializeComponent();
app.Run();
}
catch
{
System.Windows.Application.Current.Shutdown();
}
}, () =>
{
if (!System.Windows.Application.Current.Dispatcher.CheckAccess())
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
if (((App)System.Windows.Application.Current).NotifyWindow != null)
{
((App)System.Windows.Application.Current).NotifyWindow.NotifyFromRemoteApplication();
}
}));
}
else
{
if (((App)System.Windows.Application.Current).NotifyWindow != null)
{
((App)System.Windows.Application.Current).NotifyWindow.NotifyFromRemoteApplication();
}
}
}, () => !args.IsServiceMode());
}
发一个我以前的代码,不过这个是没有参数的。
如果你需要命令行参数,那么修改开始的接口方法。并且修改相应的方法。
[解决办法]
楼上的方法应该是对的。也可以用消息实现,看上去还简单些:
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Program
{
[STAThread]
private static void Main()
{
Process current = Process.GetCurrentProcess();
var runningProcess = Process.GetProcessesByName(current.ProcessName).FirstOrDefault(p => p.Id != current.Id);
if (runningProcess == null)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new WindowsApplication1.Form1());
}
else
{
var hwnd = runningProcess.MainWindowHandle;
SetForegroundWindow(hwnd);
SendMessage(hwnd, WM_COMMAND, 101, IntPtr.Zero);
}
}
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, uint wParam, IntPtr lParam);
public const int WM_COMMAND = 0x0111;
}
// Form1.cs 文件
using System;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
private TabControl _tabs;
public Form1()
{
InitializeComponent();
_tabs = new TabControl() {Dock = DockStyle.Fill};
Controls.Add(_tabs);
}
private int i = 0;
protected override void WndProc(ref Message m)
{
if (m.Msg == Program.WM_COMMAND && (uint)m.WParam == 101)
{
var page = new TabPage("File" +(++i));
_tabs.TabPages.Add(page);
return;
}
base.WndProc(ref m);
}
}
}
[解决办法]
传递参数可以用WM_COPYDATA:
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Program
{
[STAThread]
private static void Main()
{
Process current = Process.GetCurrentProcess();
var runningProcess = Process.GetProcessesByName(current.ProcessName).FirstOrDefault(p => p.Id != current.Id);
if (runningProcess == null)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new WindowsApplication1.Form1());
}
else
{
var hwnd = runningProcess.MainWindowHandle;
SetForegroundWindow(hwnd);
var cd = new COPYDATASTRUCT();
cd.lpData = "test " + DateTime.Now;
cd.cbData = cd.lpData.Length+1;
SendMessage(hwnd, WM_COPYDATA, 101, ref cd);
}
}
public struct COPYDATASTRUCT
{
public uint dwData;
public int cbData;
public string lpData;
}
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, uint wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, uint wParam, ref COPYDATASTRUCT lParam);
public const int WM_COMMAND = 0x0111;
public const int WM_COPYDATA = 74;
}
// Form1.cs 文件
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
private TabControl _tabs;
public Form1()
{
InitializeComponent();
_tabs = new TabControl() { Dock = DockStyle.Fill };
Controls.Add(_tabs);
}
private int i = 0;
protected override void WndProc(ref Message m)
{
if (m.Msg == Program.WM_COPYDATA && (uint)m.WParam == 101)
{
var cd = (Program.COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(Program.COPYDATASTRUCT));
var page = new TabPage("File" + (++i));
page.Controls.Add(new Label(){Text = cd.lpData, AutoSize = true});
_tabs.TabPages.Add(page);
return;
}
base.WndProc(ref m);
}
}
}
[解决办法]
那你就在初始化时加上page就行了:
public Form1()
{
InitializeComponent();
_tabs = new TabControl() { Dock = DockStyle.Fill };
Controls.Add(_tabs);
var page = new TabPage("File0");
_tabs.TabPages.Add(page);
}