2012-01-31 4 views
9

La mia domanda riguarda tutti i protocolli URL.Gestione protocollo URL senza riavvio applicazione

Ho registrato un protocollo URL chiamato mcm, ma ho notato che ogni volta che l'eseguo da qualsiasi browser web, t crea una nuova istanza dell'applicazione. C'è un modo per gestire la richiesta di protocollo in un'istanza già in esecuzione?

Ad esempio, quando uTorrent utilizza il protocollo torrent Gestisce immediatamente la richiesta senza eseguire nuovamente l'applicazione. Non potevo davvero trovare qualcosa di interessante su di esso, quindi mi sto chiedendo qui ...

Ecco il codice che uso per registrare il protocollo:

private static void RegisterUrlProtocol() 
{ 
    UnregisterUrlProtocol(); 

    RegistryKey rKey = Registry.ClassesRoot.OpenSubKey(UrlProtocol, true); 
    if (rKey == null) 
    { 
     rKey = Registry.ClassesRoot.CreateSubKey(UrlProtocol); 
     rKey.SetValue("", "URL: MazCraft Protocol"); 
     rKey.SetValue("URL Protocol", ""); 

     rKey = rKey.CreateSubKey(@"shell\open\command"); 
     rKey.SetValue("", "\"" + Application.ExecutablePath + "\" %1"); 
    } 

    if (rKey != null) 
    { 
     rKey.Close(); 
    } 
} 

E il codice per leggere gli argomenti:

private static bool CheckForProtocolMessage() 
{ 
    string[] arguments = Environment.GetCommandLineArgs(); 

    if (arguments.Length > 1) 
    { 
     string[] args = arguments[1].Split(':'); 
     args[1] = args[1].Replace("//", ""); 

     if (args[0].Trim().ToUpper() == "MCM" && args.Length > 1) 
     { 
      string[] actionDetail = args[1].Split('='); 

      if (actionDetail[0].Trim().ToUpper() == "INSTALL" && actionDetail.Length > 1) 
      { 
       string id = actionDetail[1].Trim().Replace("/", ""); 

       Funcs.ID = id; 

       return true; 
      } 
     } 
    } 

    return false; 
} 

Qualsiasi aiuto sarebbe molto apprezzato :) Saluti.

+5

Scommetto che se si guarda si farebbe vedere una seconda istanza di caricamento utorrent, rilevando un'istanza esistente di se stessi e comunicando a ciò tramite I PC la nuova riga di comando –

+0

Vedere anche http://stackoverflow.com/questions/917883/c-sharp-how-to-single-instance-application-that-accepts-new-parameters –

+0

Oh, in realtà ho trovato quello che ho ricercato. Grazie Alex :) –

risposta

4

È possibile utilizzare un Mutex per rilevare un'istanza dell'applicazione già in esecuzione e inviare i dati all'istanza esistente tramite Named Pipes.

Spero che l'esempio seguente sia d'aiuto. puoi scambiare l'oggetto named pipe (in questo caso string) per qualsiasi oggetto serializzabile che ti piace.

NamedPipe.cs

namespace SingleInstanceNP 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.IO.Pipes; 
    using System.Runtime.Serialization.Formatters.Binary; 
    using System.Threading; 
    using System.IO; 


    public class NamedPipe<T> : IDisposable 
    { 
     #region Attribute and Properties 

     private string _pipeName; 
     private NamedPipeServerStream _pipeServer; 
     private bool _disposed; 
     private Thread _thread; 
     private bool _started; 

     #endregion 

     #region Constructors 

     public NamedPipe(NameTypes pipeType) 
     { 
      _disposed = false; 
      _started = false; 
      _pipeName = pipeType.ToString(); 
      _thread = new Thread(Main); 
      _thread.SetApartmentState(ApartmentState.STA); 
      _thread.Name = "NamePipe: " + pipeType.ToString() + " Thread"; 
      _thread.IsBackground = true; 
     } 

     ~NamedPipe() 
     { 
      Dispose(); 
     } 

     #endregion 

     #region Events 

     public delegate void Request(T t); 
     public event Request OnRequest; 

     #endregion 

     #region Public Methods 

     public static void Send(NameTypes pipeType, T t) 
     { 
      using (var npc = new NamedPipeClientStream(".", pipeType.ToString(), PipeDirection.Out)) 
      { 
       var bf = new BinaryFormatter(); 
       npc.Connect(); 
       bf.Serialize(npc, t); 
      } 
     } 

     public static T Recieve(NameTypes pipeType) 
     { 
      using (var nps = new NamedPipeServerStream(pipeType.ToString(), PipeDirection.In)) 
      { 
       return Recieve(nps); 
      } 
     } 

     public void Start() 
     { 
      if (!_disposed && !_started) 
      { 
       _started = true; 
       _thread.Start(); 
      } 
     } 

     public void Stop() 
     { 
      _started = false; 

      if (_pipeServer != null) 
      { 
       _pipeServer.Close(); 
       // disposing will occur on thread 
      } 
     } 

     public void Dispose() 
     { 
      _disposed = true; 
      Stop(); 

      if (OnRequest != null) 
       OnRequest = null; 
     } 

     #endregion 

     private void Main() 
     { 
      while (_started && !_disposed) 
      { 
       try 
       { 
        using (_pipeServer = new NamedPipeServerStream(_pipeName)) 
        { 
         T t = Recieve(_pipeServer); 

         if (OnRequest != null && _started) 
          OnRequest(t); 
        } 
       } 
       catch (ThreadAbortException) 
       { } 
       catch (System.IO.IOException iox) 
       { 
        Console.WriteLine("ERROR: {0}", iox.Message); 
        Thread.Sleep(TimeSpan.FromSeconds(30)); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine("ERROR: {0}", ex.Message); 
        return; 
       } 
      } 
     } 

     private static T Recieve(NamedPipeServerStream nps) 
     { 
      var bf = new BinaryFormatter(); 

      try 
      { 
       nps.WaitForConnection(); 

       var obj = bf.Deserialize(nps); 

       if (obj is T) 
        return (T)obj; 
      } 
      // Catch the IOException that is raised if the pipe is 
      // broken or disconnected. 
      catch (IOException e) 
      { 
       Console.WriteLine("ERROR: {0}", e.Message); 
      } 
      return default(T); 
     } 

     #region Enums 

     public enum NameTypes 
     { 
      PipeType1 
     } 

     #endregion 
    } 
} 

Program.cs Si prega di dare credito per l'APP GUID per What is a good pattern for using a Global Mutex in C#?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using System.Reflection; 
using System.Threading; 

namespace SingleInstanceNP 
{ 
    static class Program 
    { 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      // get application GUID as defined in AssemblyInfo.cs 
      string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString(); 

      // unique id for global mutex - Global prefix means it is global to the machine 
      string mutexId = string.Format("Global\\{{{0}}}", appGuid); 

      using (var mutex = new Mutex(false, mutexId)) 
      { 
       try 
       { 
        if (!mutex.WaitOne(0, false)) 
        { 
         //signal existing app via named pipes 

         NamedPipe<string>.Send(NamedPipe<string>.NameTypes.PipeType1, "test"); 

         Environment.Exit(0); 
        } 
        else 
        { 
         // handle protocol with this instance 
         Application.Run(new Form1()); 

        } 
       } 
       finally 
       { 
        mutex.ReleaseMutex(); 
       } 
      } 
     } 
    } 
} 

Form1.cs

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 SingleInstanceNP 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
      // start listening for named pipe connections 
      var namedPipeString = new NamedPipe<string>(NamedPipe<string>.NameTypes.PipeType1); 
      namedPipeString.OnRequest += new NamedPipe<string>.Request(namedPipeString_OnRequest); 
      namedPipeString.Start(); 
     } 

     void namedPipeString_OnRequest(string t) 
     { 
      MessageBox.Show(t); 
     } 
    } 
} 
+1

-1: questa non è una risposta completa –

+0

Si prega di consultare la modifica. Dal momento che ho bisogno di un rappresentante, ho fornito un esempio funzionante. Anche @JohnSaunders non sapevo che "Qualsiasi aiuto" significava che doveva essere il codice –

+0

Ora, sai: il codice è molto preferito –