b

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/*
 11TODO: Reference the System.Runtime.Remoting assembly
 12using SellsBrothers;
 13
 14static 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
 33static void OnOtherInstance(string[] args) {
 34  TODO: Handle args from other instance
 35}
 36*/

 37
 38using System;
 39using System.Windows.Forms;
 40using System.Threading;
 41using System.Runtime.Remoting;
 42using System.Runtime.Remoting.Lifetime;
 43using System.Runtime.Remoting.Channels;
 44using System.Runtime.Remoting.Channels.Tcp;
 45
 46namespace 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), nullnull);
 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        ifthis.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        ifthis.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
posted @ 2006-07-22 00:13  -==NoWay.==-  阅读(273)  评论(0编辑  收藏  举报
c