
























SingleTon
1
// InitialInstanceActivator.cs
2
// Inspired by Mike Woodring
3
// Copyright (c) 2003, Chris Sells
4
// Notes:
5
// -Uses Application.UserAppDataPath to pick a unique string composed
6
// of the app name, the app version and the user name. This
7
// gets us a unique mutex name, channel name and port number for each
8
// user running each app of a specific version.
9
// Usage:
10
/*
11
TODO: Reference the System.Runtime.Remoting assembly
12
using SellsBrothers;
13

14
static void Main(string[] args) {
15
// Check for initial instance, registering callback to consume args from other instances
16
// Main form will be activated automatically
17
OtherInstanceCallback callback = new OtherInstanceCallback(OnOtherInstance);
18
if( InitialInstanceActivator.Activate(mainForm, callback, args) ) return;
19
20
// Check for initial instance w/o registering a callback
21
// Main form will still be activated automatically
22
if( InitialInstanceActivator.Activate(mainForm) ) return;
23
24
// Check for initial instance, registering callback to consume args from other instances
25
// Main form from ApplicationContext will be activated automatically
26
OtherInstanceCallback callback = new OtherInstanceCallback(OnOtherInstance);
27
if( InitialInstanceActivator.Activate(context, callback, args) ) return;
28
29
TODO: Run application
30
}
31
32
// Called from other instances
33
static void OnOtherInstance(string[] args) {
34
TODO: Handle args from other instance
35
}
36
*/
37
38
using System;
39
using System.Windows.Forms;
40
using System.Threading;
41
using System.Runtime.Remoting;
42
using System.Runtime.Remoting.Lifetime;
43
using System.Runtime.Remoting.Channels;
44
using System.Runtime.Remoting.Channels.Tcp;
45
46
namespace SellsBrothers {
47
// Signature of method to call when another instance is detected
48
public delegate void OtherInstanceCallback(string[] args);
49
50
public class InitialInstanceActivator {
51
public static int Port {
52
get {
53
// Pick a port based on an application-specific string
54
// that also falls into an exceptable range
55
return Math.Abs(ChannelName.GetHashCode()/2)%(short.MaxValue - 1024) + 1024;
56
}
57
}
58
59
public static string ChannelName {
60
get {
61
return Application.UserAppDataPath.ToLower().Replace(@"\", "_");
62
}
63
}
64
65
public static string MutexName {
66
get {
67
return ChannelName;
68
}
69
}
70
71
public static bool Activate(Form mainForm) {
72
return Activate(new ApplicationContext(mainForm), null, null);
73
}
74
75
public static bool Activate(Form mainForm, OtherInstanceCallback callback, string[] args) {
76
return Activate(new ApplicationContext(mainForm), callback, args);
77
}
78
79
public static bool Activate(ApplicationContext context, OtherInstanceCallback callback, string[] args) {
80
// Check for existing instance
81
bool firstInstance = false;
82
Mutex mutex = new Mutex(true, MutexName, out firstInstance);
83
84
if( !firstInstance ) {
85
// Open remoting channel exposed from initial instance
86
string url = string.Format("tcp://localhost:{0}/{1}", Port, ChannelName);
87
MainFormActivator activator = (MainFormActivator)RemotingServices.Connect(typeof(MainFormActivator), url);
88
89
// Send arguments to initial instance and exit this one
90
activator.OnOtherInstance(args);
91
return true;
92
}
93
94
// Expose remoting channel to accept arguments from other instances
95
ChannelServices.RegisterChannel(new TcpChannel(Port));
96
RemotingServices.Marshal(new MainFormActivator(context, callback), ChannelName);
97
return false;
98
}
99
100
public class MainFormActivator : MarshalByRefObject {
101
public MainFormActivator(ApplicationContext context, OtherInstanceCallback callback) {
102
this.context = context;
103
this.callback = callback;
104
}
105
106
public override object InitializeLifetimeService() {
107
// We want an infinite lifetime as far as the
108
// remoting infrastructure is concerned
109
// (Thanks for Mike Woodring for pointing this out)
110
ILease lease = (ILease)base.InitializeLifetimeService();
111
lease.InitialLeaseTime = TimeSpan.Zero;
112
return(lease);
113
}
114
115
public void OnOtherInstance(string[] args) {
116
// Transition to the UI thread
117
if( this.context.MainForm.InvokeRequired ) {
118
OtherInstanceCallback callback = new OtherInstanceCallback(OnOtherInstance);
119
this.context.MainForm.Invoke(callback, new object[] { args });
120
return;
121
}
122
123
// Let the UI thread know about the other instance
124
if( this.callback != null ) this.callback(args);
125
126
// Activate the main form
127
context.MainForm.Activate();
128
}
129
130
ApplicationContext context;
131
OtherInstanceCallback callback;
132
}
133
}
134
}
135
136
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。