2010-06-18 16 views
6

Actualmente mantengo una aplicación interna en .Net. La aplicación utiliza IPC para mantener una sesión de ejecución a la vez; si intenta abrir otra sesión (Alguien vuelve a hacer clic en el icono, algunos abren un archivo de resultados guardado), la segunda sesión lo comunica a la primera sesión y luego finaliza, con la primera sesión y luego iniciando la acción solicitada.¿Cómo usar IPC sin ser un administrador local?

Actualmente hago esto utilizando el espacio de nombres System.ServiceModel, así:

espacio de nombres EventLogViewer.IPCServer {// proporciona el marco común para los procesos comunicarse a contactar a los demás.

[ServiceContract(Namespace = "http://ELV.domain")] 
interface IELVLauncher 
{ 
    [OperationContract] 
    bool LaunchTabs(String[] fileNames); 
} 
public delegate void TabLauncher(String[] fileNames); 
class ELVLauncherServer : IDisposable 
{ 
    ServiceHost ipcService; 
    public ELVLauncherServer() 
    { 
     Uri baseAddress = new Uri("Http://localhost:45600/elvlauncher/service"); 
     String address = "net.pipe://localhost/elvlauncher/tablauncher"; 

     ipcService = new ServiceHost(typeof(ELVLauncher), baseAddress); 

     NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); 
     ipcService.AddServiceEndpoint(typeof(IELVLauncher), binding, address); 

     ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); 
     behavior.HttpGetEnabled = true; 
     behavior.HttpGetUrl = new Uri("http://localhost:45601/elvlauncher"); 
     ipcService.Description.Behaviors.Add(behavior); 
     Utilities.WriteMemoryDebugStatement(new DebugStatement(DebugStatement.StatementType.INFO, "Registering IPC Service")); 
     ipcService.Open(); 

    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     ipcService.Close(); 
    } 

    #endregion 
} 
public class ELVLauncher : IELVLauncher 
{ 
    #region IELVLauncher Members 

    public bool LaunchTabs(string[] fileNames) 
    { 
     try 
     { 
      Utilities.WriteMemoryDebugStatement(new DebugStatement(DebugStatement.StatementType.INFO, String.Format("IPC request received, files: {0}", String.Join(", ", fileNames)))); 
      Program.mainWindow.backgroundListener_OnLaunchRequestReceived(fileNames); 
     } 
     catch (Exception exception) 
     { 
      Utilities.WriteMemoryDebugStatement(new DebugStatement(exception)); 
     } 
     return (true); 
    } 

    #endregion 

} 

Este código fue desarrollado originalmente bajo Windows XP, ya que al igual que la mayoría de las corporaciones, no pasamos a Vista. Como todos nos ejecutamos como administradores locales, este código se ejecutó sin problemas.

Sin embargo, estamos haciendo la transición a Win 7 ahora, y este código produce una excepción al inicio porque no puede registrar el punto final de IPC. Más información aquí: http://mark.michaelis.net/Blog/WindowsCommunicationFoundationWithWindowsVistaAndUAC.aspx

La solución dada es subir la aplicación para requerir privilegios de administrador. Esto no funciona por dos razones:

  1. Esta aplicación no necesita privledges de administración de otra forma
  2. Utilizamos ClickOnce para el despliegue de nuestras herramientas internas y ClickOnce no apoya que no sea correr como el lanzador proceso de nada.

Así que en este punto tengo que encontrar una solución IPC que no requiere privledges de administración y me permite lograr el objetivo original: la detección de una instancia en ejecución del código y le dice qué hacer, de lo contrario el lanzamiento en sí. Cualquier sugerencia sobre qué hacer (dentro del marco .Net, sin soluciones de terceros, por favor) sería muy apreciada.

+1

No repita las etiquetas ".Net 3.5 C#:" en el título. –

Respuesta

3

Esa es una manera increíblemente difícil (y como usted ha descubierto, problemática) de garantizar una sola sesión de su aplicación. Debería simplemente refactorizar/rehacer la función a use a mutex.

Aquí hay otro example. Y el requisito wiki article about mutexes.

EDITAR

Para moverse por el bit de comunicación que podría generar un archivo temporal con su propio prefijo y o extensión especial en la carpeta temporal del sistema operativo proporcionado por la cual sería sondear la sola aplicación (filtrado para su prefijo especial y/o extensión) para ver si se hicieron más solicitudes. Ver:

System.IO.Path.GetTempFileName 

y

System.IO.Path.GetTempPath 
+0

bonificación: se puede crear un Mutex sin privilegios de administrador. – Cheeso

+0

@ Cheeso: exactamente.Supongo que debería ser explícito al respecto en la respuesta. –

+0

Gracias, pero esto solo resuelve la mitad del problema. El segundo proceso tiene que decirle al primero lo que iba a hacer (iniciar, cargar un informe guardado). Los mutexes no permiten eso. – Dan

Cuestiones relacionadas