InitialInstanceActivator
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
// InitialInstanceActivator.cs2
// Inspired by Mike Woodring3
// Copyright (c) 2003, Chris Sells4
// Notes:5
// -Uses Application.UserAppDataPath to pick a unique string composed6
// of the app name, the app version and the user name. This7
// gets us a unique mutex name, channel name and port number for each8
// user running each app of a specific version.9
// Usage:10
/*11
TODO: Reference the System.Runtime.Remoting assembly12
using SellsBrothers;13


14
static void Main(string[] args) {15
// Check for initial instance, registering callback to consume args from other instances16
// Main form will be activated automatically17
OtherInstanceCallback callback = new OtherInstanceCallback(OnOtherInstance);18
if( InitialInstanceActivator.Activate(mainForm, callback, args) ) return;19
20
// Check for initial instance w/o registering a callback21
// Main form will still be activated automatically22
if( InitialInstanceActivator.Activate(mainForm) ) return;23

24
// Check for initial instance, registering callback to consume args from other instances25
// Main form from ApplicationContext will be activated automatically26
OtherInstanceCallback callback = new OtherInstanceCallback(OnOtherInstance);27
if( InitialInstanceActivator.Activate(context, callback, args) ) return;28

29
TODO: Run application30
}31

32
// Called from other instances33
static void OnOtherInstance(string[] args) {34
TODO: Handle args from other instance35
}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 detected48
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 string54
// that also falls into an exceptable range55
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 instance81
bool firstInstance = false;82
Mutex mutex = new Mutex(true, MutexName, out firstInstance);83

84
if( !firstInstance ) {85
// Open remoting channel exposed from initial instance86
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 one90
activator.OnOtherInstance(args);91
return true;92
}93

94
// Expose remoting channel to accept arguments from other instances95
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 the108
// remoting infrastructure is concerned109
// (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 thread117
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 instance124
if( this.callback != null ) this.callback(args);125

126
// Activate the main form127
context.MainForm.Activate();128
}129

130
ApplicationContext context;131
OtherInstanceCallback callback;132
}133
}134
}135

136



浙公网安备 33010602011771号