private void btnAgentCloseAllGui_Click(object sender, EventArgs e)
 {
     foreach (var agentId in GetSelectedAgentIds())
     {
         Tuple <SynchronizationContext, IAgentUI> agentUI;
         if (_agentUIs.TryRemove(agentId, out agentUI))
         {
             UIThreadingHelper.DispatchUI(agentUI.Item2.CloseUI, agentUI.Item1);
         }
     }
 }
        private async Task ShowAgentUI(string agentId, IVisibleAgent agent)
        {
            if (string.IsNullOrEmpty(agentId))
            {
                throw new ArgumentNullException("agentId");
            }
            if (agent == null)
            {
                throw new ArgumentNullException("agent");
            }

            Tuple <SynchronizationContext, IAgentUI> agentUI;

            if (_agentUIs.TryGetValue(agentId, out agentUI))
            {
                UIThreadingHelper.DispatchUI(agentUI.Item2.ShowUI, agentUI.Item1);
            }
            else
            {
                var uiAgentTypeNameResult = await AgentBroker.Instance.TryExecuteOnOne <IVisibleAgent, string>(agentId, a => a.MainUIAgentTypeName).ConfigureAwait(false);

                if (!uiAgentTypeNameResult.IsSuccessful)
                {
                    UIThreadingHelper.DispatchUI(() => MessageBox.Show(this, string.Format("The UI cannot be shown because of a communication error with agent '{0}'.\n\n{1}", agentId, uiAgentTypeNameResult.Exception), "Show UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error), _mainSynchronizationContext);
                    return;
                }

                var getAgentResult = AgentBroker.Instance.TryGetAgent(Type.GetType(uiAgentTypeNameResult.Result), agentId);
                if (getAgentResult.Item1 != TryGetAgentResult.Success)
                {
                    UIThreadingHelper.DispatchUI(() => MessageBox.Show(this, string.Format("The UI cannot be shown because of an internal error from agent '{0}' ('{1}').", agentId, getAgentResult), "Show UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error), _mainSynchronizationContext);
                    return;
                }

                var uiTypeNameResult = await AgentBroker.Instance.TryExecuteOnOne <IVisibleAgent, string>(agentId, a => a.MainUITypeName).ConfigureAwait(false);

                if (!uiTypeNameResult.IsSuccessful)
                {
                    UIThreadingHelper.DispatchUI(() => MessageBox.Show(this, string.Format("The UI cannot be shown because of a communication error with agent '{0}'.\n\n{1}", agentId, uiTypeNameResult.Exception), "Show UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error), _mainSynchronizationContext);
                    return;
                }

                var guiType = Type.GetType(uiTypeNameResult.Result);
                if (guiType == null)
                {
                    UIThreadingHelper.DispatchUI(() => MessageBox.Show(this, string.Format("The UI cannot be shown because the library for agent '{0}' is not available locally.", agentId), "Show UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error), _mainSynchronizationContext);
                    return;
                }

                UIThreadingHelper.RunInNewUIThread(
                    () =>
                {
                    var ui = (IAgentUI)Activator.CreateInstance(guiType);
                    _agentUIs.TryAdd(agentId, Tuple.Create(SynchronizationContext.Current, ui));

                    ui.UIClosed += (s2, e2) => _agentUIs.TryRemove(agentId, out agentUI);
                    ui.Initialize(getAgentResult.Item3);
                    ui.ShowUI();
                });
            }
        }
        private Task StartStopService()
        {
            if (AgentBroker.Instance.State == ServiceState.Started)
            {
                return(Task.WhenAll(_agentUIs.Values.Select(agentUI => Task.Run(() => UIThreadingHelper.DispatchUI(agentUI.Item2.CloseUI, agentUI.Item1, asynchronous: false))))
                       .ContinueWith(t => AgentBroker.Instance.Stop())
                       .ContinueWith(
                           t =>
                {
                    if (t.IsFaulted)
                    {
                        MessageBox.Show(t.Exception.ToString(), "Stop has failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else if (t.IsCanceled)
                    {
                        MessageBox.Show(t.Exception.ToString(), "Stop canceled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }, TaskScheduler.FromCurrentSynchronizationContext()));
            }
            else if (AgentBroker.Instance.State == ServiceState.Stopped)
            {
                AgentBroker.Instance.LoadConfiguration(_brokerConfigurationFilePath);

                PlaySound("startup");

                return(AgentBroker.Instance.Start()
                       .ContinueWith(
                           t =>
                {
                    if (t.IsFaulted)
                    {
                        MessageBox.Show(t.Exception.ToString(), "Start has failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else if (t.IsCanceled)
                    {
                        MessageBox.Show(string.Format("Start has been canceled: {0}", t.Exception), "Start canceled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }, TaskScheduler.FromCurrentSynchronizationContext()));
            }
            else
            {
                throw new InvalidOperationException(string.Format("Service state must be '{0}' or '{1}', but current state is '{2}'.", ServiceState.Started, ServiceState.Stopped, AgentBroker.Instance.State));
            }
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            this.RegisterObserver(
                this.UIThemeDataSource
                .ObserveOn(WindowsFormsSynchronizationContext.Current)
                .Subscribe(
                    uiTheme =>
            {
                gridAgents.ThemeName     = uiTheme.Theme.ThemeName;
                this.BackColor           = uiTheme.BackColor;
                txtInformation.BackColor = uiTheme.BackColor;
                txtInformation.ForeColor = uiTheme.ForeColor;
            }));

            this.RegisterObserver(
                AgentBroker.Instance.StateDataSource
                .ObserveOn(WindowsFormsSynchronizationContext.Current)
                .Subscribe(
                    state =>
            {
                switch (state)
                {
                case ServiceState.Starting:
                    txtInformation.Text         = "Starting";
                    btnServiceStartStop.Enabled = false;
                    break;

                case ServiceState.Started:
                    ttMain.SetToolTip(btnServiceStartStop, "Stop service");
                    txtInformation.Text = string.Format("Started ({0} - {1}:{2})", AgentBroker.Instance.LocalPeerNode.Description, AgentBroker.Instance.LocalPeerNode.Host, AgentBroker.Instance.LocalPeerNode.Port);

                    btnServiceStartStop.Image   = ImageResources.ServiceStop;
                    btnServiceStartStop.Enabled = true;
                    break;

                case ServiceState.Stopping:
                    txtInformation.Text         = "Stopping";
                    btnServiceStartStop.Enabled = false;
                    break;

                case ServiceState.Stopped:
                    _agentUIs.Clear();
                    _agents.Clear();

                    // grid does not clear selection automatically
                    gridAgents.ClearSelection();

                    ttMain.SetToolTip(btnServiceStartStop, "Start service");
                    txtInformation.Text = "Not started";

                    btnServiceStartStop.Image   = ImageResources.ServiceStart;
                    btnServiceStartStop.Enabled = true;
                    break;
                }
            }));

            this.RegisterObserver(
                AgentBroker.Instance.AgentDataSource
                .ObserveOn(WindowsFormsSynchronizationContext.Current)
                .Subscribe(
                    info =>
            {
                var row = _agents.Rows.Find(info.AgentId);

                if (row == null)
                {
                    row = _agents.NewRow();
                }

                row["peer"]        = info.PeerNode.ToString();
                row["name"]        = info.DisplayData.Name;
                row["description"] = info.DisplayData.Description;
                row["isInternal"]  = info.IsInternal;
                row["state"]       = info.LastKnownState;
                row["reachable"]   = info.IsReachable;

                if (row.RowState == DataRowState.Detached)
                {
                    row["id"] = info.AgentId;
                    _agents.Rows.Add(row);
                }

                if (info.LastKnownState == AgentState.Disposed || info.IsRecycled)
                {
                    Tuple <SynchronizationContext, IAgentUI> agentUI;
                    if (_agentUIs.TryRemove(info.AgentId, out agentUI))
                    {
                        UIThreadingHelper.DispatchUI(agentUI.Item2.CloseUI, agentUI.Item1);
                    }
                }
            }));

            this.RegisterObserver(
                AgentBroker.Instance.AgentDataSource
                .Where(info => info.LastKnownState == AgentState.Activated)
                .Subscribe(
                    info =>
            {
                var getAgentResult = AgentBroker.Instance.TryGetAgent <IVisibleAgent>(info.AgentId);

#pragma warning disable 4014
                if (getAgentResult.Item1 == TryGetAgentResult.Success && getAgentResult.Item2.IsLocal && getAgentResult.Item3.AutoShowUI)
                {
                    ShowAgentUI(info.AgentId, getAgentResult.Item3);
                }
#pragma warning restore 4014
            }));

            ErrorHandler.Try(
                () => AgentBroker.Instance.LoadConfiguration(_brokerConfigurationFilePath),
                "Configuration load error.",
                "An error occurred while loading configuration.",
                canRetry: true)
            .ContinueWith(
                t =>
            {
                if (t.IsCompleted && t.Result)
                {
                    if (AgentBroker.Instance.Configuration.AutoShowLogWindow)
                    {
                        ShowLogWindow();
                    }

                    if (AgentBroker.Instance.Configuration.AutoStartBroker)
                    {
                        StartStopService();
                    }
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
 private static void STASetClipboardText(string text)
 {
     UIThreadingHelper.DispatchUI(() => Clipboard.SetText(text));
 }