Именованные каналы WCF через сеанс пользователя на одном компьютере. Возможный? - PullRequest
0 голосов
/ 12 февраля 2020

Требование Я пытаюсь создать приложение winforms "Единого экземпляра" с аргументами, которые необходимо передать, если будет вызван второй экземпляр. Я надеюсь Mutex не будет работать так. Я создал канал WCF в приложении winform, чтобы, если пришел другой экземпляр, он был уведомлен в главном экземпляре с необходимыми аргументами, и я обработаю аргументы в главном экземпляре по мере необходимости, а второй экземпляр закроется после уведомления.

Проблема: Кажется, что вышеприведенный код работает нормально, проблема возникает, когда речь идет о многопользовательском сеансе. Когда я подключаюсь к компьютеру как «Пользователь A» и открываю свое приложение, оно открывает приложение (основной экземпляр). В то же время, если другой пользователь входит в систему и говорит «Пользователь B» и пытается открыть приложение, ЭТО СЧАСТЛИВО РАБОТАЕТ: (

Код:

Вот мой код для одного экземпляра с WCF.

public static class SingleInstanceManager
{
    /// <summary>
    /// Raised when another instance attempts to start up.
    /// </summary>
    public static event StartupEventHandler OtherInstanceStarted;

    /// <summary>
    /// Checks to see if this instance is the first instance running on this machine.  If it is not, this method will
    /// send the main instance this instance's startup information.
    /// </summary>
    /// <param name="guid">The application's unique identifier.</param>
    /// <returns>True if this instance is the main instance.</returns>
    public static bool VerifySingleInstance(Guid guid)
    {
        if (!AttemptPublishService(guid))
        {
            NotifyMainInstance(guid);

            return false;
        }

        return true;
    }

    /// <summary>
    /// Attempts to publish the service.
    /// </summary>
    /// <param name="guid">The application's unique identifier.</param>
    /// <returns>True if the service was published successfully.</returns>
    private static bool AttemptPublishService(Guid guid)
    {
        try
        {
            ServiceHost serviceHost = new ServiceHost(typeof(SingleInstance));
            NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
            serviceHost.AddServiceEndpoint(typeof(ISingleInstance), binding, CreateAddress(guid));
            serviceHost.Open();

            return true;
        }
        catch
        {
            return false;
        }
    }

    /// <summary>
    /// Notifies the main instance that this instance is attempting to start up.
    /// </summary>
    /// <param name="guid">The application's unique identifier.</param>
    private static void NotifyMainInstance(Guid guid)
    {
        NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
        EndpointAddress remoteAddress = new EndpointAddress(CreateAddress(guid));
        using (ChannelFactory<ISingleInstance> factory = new ChannelFactory<ISingleInstance>(binding, remoteAddress))
        {
            ISingleInstance singleInstance = factory.CreateChannel();
            singleInstance.NotifyMainInstance(Environment.GetCommandLineArgs());
        }
    }

    /// <summary>
    /// Creates an address to publish/contact the service at based on a globally unique identifier.
    /// </summary>
    /// <param name="guid">The identifier for the application.</param>
    /// <returns>The address to publish/contact the service.</returns>
    private static string CreateAddress(Guid guid)
    {
        return string.Format(CultureInfo.CurrentCulture, "net.pipe://localhost/{0}", guid);
    }

    /// <summary>
    /// The interface that describes the single instance service.
    /// </summary>
    [ServiceContract]
    private interface ISingleInstance
    {
        /// <summary>
        /// Notifies the main instance that another instance of the application attempted to start.
        /// </summary>
        /// <param name="args">The other instance's command-line arguments.</param>
        [OperationContract]
        void NotifyMainInstance(string[] args);
    }

    /// <summary>
    /// The implementation of the single instance service interface.
    /// </summary>
    private class SingleInstance : ISingleInstance
    {
        /// <summary>
        /// Notifies the main instance that another instance of the application attempted to start.
        /// </summary>
        /// <param name="args">The other instance's command-line arguments.</param>
        public void NotifyMainInstance(string[] args)
        {
            if (OtherInstanceStarted != null)
            {
                Type type = typeof(StartupEventArgs);
                ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
                StartupEventArgs e = (StartupEventArgs)constructor.Invoke(null);
                FieldInfo argsField = type.GetField("_args", BindingFlags.Instance | BindingFlags.NonPublic);
                Debug.Assert(argsField != null);
                argsField.SetValue(e, args);

                OtherInstanceStarted(null, e);
            }
        }
    }
}

На Winforms Main:

static void Main()
{
  //bool isSingle;
  //var mut = new Mutex(true, "MarketFeeder", out isSingle);
  var applicationId = new Guid("08f21b4e-86d7-4ddf-abcb-9a72cd2bbd4f");

   if (SingleInstanceManager.VerifySingleInstance(applicationId))
    {
        SingleInstanceManager.OtherInstanceStarted += OnOtherInstanceStarted;
            // Start the application

        System.Windows.Forms.Application.EnableVisualStyles();
        System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
        main = new MainForm();
        System.Windows.Forms.Application.Run(main);
    }     

}

Требуется помощь по

Есть ли способ общаться через Namedpipe между пользователями на одной и той же машине ?, я не хочу go для "Windows service" для моего требования, которое я чувствую чрезмерно для моего требования.

Уже прошло, хотя следующее ссылки, но не повезло. Кроме того, они слишком стары. Я чувствую, что в последнее время у нас есть лучшее решение для этого. Я надеюсь, что есть такие разработчики, как я, которые все еще работают над Windows приложениями: P

Изолированные именованные каналы в сеансах сервера терминалов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...