Attualmente mantengo un'applicazione interna in .Net. L'applicazione utilizza IPC per mantenere una sessione in esecuzione alla volta; se un'altra sessione tenta di aprirsi (Qualcuno fa nuovamente clic sull'icona, alcuni apre un file dei risultati salvato), la seconda sessione lo comunica alla prima sessione e quindi termina, con la prima sessione che quindi avvia l'azione richiesta.Come utilizzare IPC senza essere un amministratore locale?
Io attualmente faccio utilizzando il namespace System.ServiceModel, in questo modo:
namespace EventLogViewer.IPCServer {// fornisce il quadro comune per i processi di comunicare a oneanother.
[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
}
Questo codice è stato originariamente sviluppato in ambiente Windows XP, come come la maggior parte delle aziende non ci siamo mossi a Vista. Dato che tutti eseguiamo come amministratori locali, questo codice ha funzionato senza problemi.
Tuttavia, stiamo passando a Win 7 ora e questo codice genera un'eccezione all'avvio perché non può registrare l'endpoint IPC. Ulteriori informazioni sono disponibili al seguente indirizzo: http://mark.michaelis.net/Blog/WindowsCommunicationFoundationWithWindowsVistaAndUAC.aspx
La soluzione proposta consiste nell'applicare l'app per richiedere i privilegi di amministratore. Questo non funziona per due motivi:
- Questa applicazione non necessita di privilegi di Admin altrimenti
- Usiamo ClickOnce per la distribuzione dei nostri strumenti interni ed ClickOnce non sosteniamo altro che correre come il programma di avvio del processo.
Quindi a questo punto ho bisogno di trovare una soluzione IPC che non richiede privilegi di admin e mi permette di raggiungere l'obiettivo originale: rilevare un'istanza già in esecuzione del codice e dirgli che cosa fare, altrimenti il lancio stesso. Qualsiasi suggerimento su cosa fare (all'interno del framework .Net, nessuna soluzione di terze parti per favore) sarebbe molto apprezzato.
Si prega di non ripetere tag ".Net 3.5 C#:" nel titolo. Bonus –