Я в настоящее время поддерживаю внутреннее приложение в .NET. Приложение использует IPC для поддержания одной рабочей сессии за один раз; если другая попытка сессии открыться (Кто-то нажимает значок снова, некоторые открывают сохраненный файл результата), вторая сессия передает это на первую сессию и затем завершается с первой сессией, затем запускающей требуемое действие.
Я в настоящее время делаю это использование Система. Пространство имен ServiceModel, как так:
пространство имен EventLogViewer. IPCServer {//Служит общей основой для процессов для передачи с 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
}
Этот код был первоначально разработан под Windows XP, так же как большинство корпораций, которые мы не перемещали в Vista. Так как все мы работаем как локальные администраторы, этот код работал без проблемы.
Однако мы переходим к Win 7 теперь, и этот код производит исключение на запуске, потому что это не может зарегистрировать конечную точку IPC. Больше информации здесь: http://mark.michaelis.net/Blog/WindowsCommunicationFoundationWithWindowsVistaAndUAC.aspx
Данное обходное решение к приложению к требованию администратора privledges. Это не работает по двум причинам:
Таким образом в этой точке я должен найти решение IPC, которое не требует администратора privledges и позволяет мне достигнуть исходной цели: обнаружение уже рабочего экземпляра кода и сообщения его, что сделать, иначе запустив себя. Любые предложения на том, что сделать (в платформе .NET, никакие решения других производителей) очень ценились бы.
Это невероятно сложный (и, как вы обнаружили, проблемный способ) обеспечить единый сеанс вашего приложения. Вам нужно просто выполнить рефакторинг / повторить эту функцию, чтобы использовать мьютекс .
Вот еще один пример . И необходимая вики-статья о мьютексах .
РЕДАКТИРОВАТЬ
Чтобы обойти бит связи, вы можете сгенерировать временный файл со своим собственным специальным префиксом и / или расширением в предоставленной ОС временной папке, которую будет опрашивать одно приложение (фильтрация по вашему специальному префиксу и / или расширению) чтобы узнать, поступали ли еще запросы. См .:
System.IO.Path.GetTempFileName
и
System.IO.Path.GetTempPath
Определенно используйте именованный мьютекс , чтобы ограничить приложение одним экземпляром, тогда вы можете использовать NamedPipeServerStream и NamedPipeClientStream для выполнения IPC, который не требует права администратора.