Skip to content

Commit

Permalink
Merge pull request #9 from RXDSolutions/feature/diagnotics
Browse files Browse the repository at this point in the history
Feature/diagnotics
  • Loading branch information
rosssaunders authored Jul 2, 2019
2 parents 0d1be5f + 30caa0b commit dcb0198
Show file tree
Hide file tree
Showing 93 changed files with 3,683 additions and 549 deletions.
Binary file added libs/RXDSolutions/7_1/Sophis.Windows.dll
Binary file not shown.
Binary file modified libs/RXDSolutions/7_1/SophisDotNetToolkit.dll
Binary file not shown.
Binary file modified libs/RXDSolutions/7_1/SophisDotNetToolkit.pdb
Binary file not shown.
Binary file added libs/RXDSolutions/7_2/Sophis.Windows.dll
Binary file not shown.
Binary file modified libs/RXDSolutions/7_2/SophisDotNetToolkit.dll
Binary file not shown.
Binary file modified libs/RXDSolutions/7_2/SophisDotNetToolkit.pdb
Binary file not shown.
Binary file modified libs/RXDSolutions/MFCCaptionBar10.dll
Binary file not shown.
12 changes: 8 additions & 4 deletions src/Clients/ExcelClient/AddIn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class AddIn : IExcelAddIn
//The client needs to be static so the Excel functions (which must be static) can access it.
public static DataServiceClient Client;
public static ConnectionMonitor ConnectionMonitor;
public static AvailableConnections AvailableConnections;

public static bool IsShuttingDown;

Expand All @@ -32,15 +33,18 @@ public void AutoOpen()
var app = ExcelDnaUtil.Application as Microsoft.Office.Interop.Excel.Application;
app.RTD.ThrottleInterval = 100;

//Monitor for FusionLink connections
AvailableConnections = new AvailableConnections();

//Open the client connection
ConnectionMonitor = new ConnectionMonitor();
ConnectionMonitor = new ConnectionMonitor(AvailableConnections);
ConnectionMonitor.RegisterClient(Client);
ExcelComAddInHelper.LoadComAddIn(new ComAddIn(Client, ConnectionMonitor));
ExcelComAddInHelper.LoadComAddIn(new ComAddIn(Client, ConnectionMonitor, AvailableConnections));

Client.OnConnectionStatusChanged += Client_OnConnectionStatusChanged;

//Start the monitor
ConnectionMonitor.FindAvailableServicesAsync().ContinueWith(result =>
AvailableConnections.FindAvailableServicesAsync().ContinueWith(result =>
{
if (IsShuttingDown)
return;
Expand Down
253 changes: 253 additions & 0 deletions src/Clients/ExcelClient/AvailableConnections.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Discovery;
using System.Text;
using System.Threading.Tasks;
using RxdSolutions.FusionLink.Interface;

namespace RxdSolutions.FusionLink.ExcelClient
{
public class AvailableConnections : IDisposable
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);

public event EventHandler<EventArgs> AvailableEndpointsChanged;

public bool IsSearchingForEndPoints { get; private set; }

private readonly List<EndpointAddress> _availableEndpoints;
private readonly ServiceHost _announcementServiceHost;
private readonly AnnouncementService _announcementService;

public AvailableConnections()
{
_availableEndpoints = new List<EndpointAddress>();

// Subscribe the announcement events
_announcementService = new AnnouncementService();
_announcementService.OnlineAnnouncementReceived += OnOnlineEvent;
_announcementService.OfflineAnnouncementReceived += OnOfflineEvent;

// Create ServiceHost for the AnnouncementService
_announcementServiceHost = new ServiceHost(_announcementService);
_announcementServiceHost.AddServiceEndpoint(new UdpAnnouncementEndpoint());
_announcementServiceHost.Open();
}

public IReadOnlyList<EndpointAddress> AvailableEndpoints
{
get
{
lock (_availableEndpoints)
{
return _availableEndpoints.ToList();
}
}
}

public Task FindAvailableServicesAsync()
{
IsSearchingForEndPoints = true;

return Task.Run(() => {

FindAvailableServices();

});
}

public void FindAvailableServices()
{
try
{
IsSearchingForEndPoints = true;

AvailableEndpointsChanged?.Invoke(this, new EventArgs());

var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());

var findResponse = discoveryClient.Find(new FindCriteria(typeof(IDataServiceServer)) { Duration = TimeSpan.FromSeconds(3) });

discoveryClient.Close();

int SessionIdFromUri(EndpointDiscoveryMetadata metaData)
{
if (int.TryParse(metaData.ListenUris[0].Segments[2].Replace("/", ""), out int sessionId))
{
return sessionId;
}

return 0;
}

int ProcessIdFromUri(EndpointDiscoveryMetadata metaData)
{
if (int.TryParse(metaData.ListenUris[0].Segments[3].Replace("/", ""), out int processId))
{
return processId;
}

return 0;
}

foreach (var endPoint in findResponse.Endpoints)
{
if (string.Compare(endPoint.ListenUris[0].Host, Environment.MachineName, StringComparison.InvariantCultureIgnoreCase) != 0)
{
continue;
}

if (SessionIdFromUri(endPoint) != Process.GetCurrentProcess().SessionId)
{
continue;
}

//Check the process is running under the same user account
var processId = ProcessIdFromUri(endPoint);

if (processId == 0)
continue;

var remoteProcess = Process.GetProcessById(processId);
if (remoteProcess == null)
continue;

if(!GetProcessUser(remoteProcess).User.Value.Equals(WindowsIdentity.GetCurrent().User.Value))
{
continue;
}

var found = false;

foreach (var knownEndpoint in AvailableEndpoints)
{
if (knownEndpoint.Uri == endPoint.Address.Uri)
{
found = true;
break;
}
}

if (!found)
{
lock (_availableEndpoints)
{
_availableEndpoints.Add(endPoint.Address);
AvailableEndpointsChanged?.Invoke(this, new EventArgs());
}
}
}

foreach (var knownEndpoint in AvailableEndpoints)
{
var found = false;
foreach (var endPoints in findResponse.Endpoints)
{
if (knownEndpoint.Uri == endPoints.Address.Uri)
{
found = true;
break;
}
}

if (!found)
{
lock (_availableEndpoints)
{
_availableEndpoints.Remove(knownEndpoint);
AvailableEndpointsChanged?.Invoke(this, new EventArgs());
}
}
}
}
finally
{
IsSearchingForEndPoints = false;

AvailableEndpointsChanged?.Invoke(this, new EventArgs());
}
}

public void Remove(EndpointAddress ea)
{
_availableEndpoints.Remove(ea);

AvailableEndpointsChanged?.Invoke(this, new EventArgs());
}

private void OnOfflineEvent(object sender, AnnouncementEventArgs e)
{
_availableEndpoints.Remove(e.EndpointDiscoveryMetadata.Address);
AvailableEndpointsChanged?.Invoke(this, new EventArgs());
}

private void OnOnlineEvent(object sender, AnnouncementEventArgs e)
{
_availableEndpoints.Add(e.EndpointDiscoveryMetadata.Address);
AvailableEndpointsChanged?.Invoke(this, new EventArgs());
}

public EndpointAddress FindEndpoint(Uri connection)
{
lock (_availableEndpoints)
{
return _availableEndpoints.SingleOrDefault(x => x.Uri == connection);
}
}

#region IDisposable Support

private bool disposedValue = false;

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_announcementServiceHost.Close();
}

disposedValue = true;
}
}

public void Dispose()
{
Dispose(true);
}

#endregion

private static WindowsIdentity GetProcessUser(Process process)
{
IntPtr processHandle = IntPtr.Zero;
try
{
OpenProcessToken(process.Handle, 8, out processHandle);
return new WindowsIdentity(processHandle);
}
catch
{
return null;
}
finally
{
if (processHandle != IntPtr.Zero)
{
CloseHandle(processHandle);
}
}
}
}
}
9 changes: 5 additions & 4 deletions src/Clients/ExcelClient/ComAddIn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,23 @@ public class ComAddIn : ExcelComAddIn
{
private readonly DataServiceClient client;
private readonly ConnectionMonitor monitor;
private readonly AvailableConnections availableConnections;

public ComAddIn(DataServiceClient client, ConnectionMonitor monitor)
public ComAddIn(DataServiceClient client, ConnectionMonitor monitor, AvailableConnections availableConnections)
{
this.client = client;
this.monitor = monitor;
this.availableConnections = availableConnections;
}

public override void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom)
{
AddIn.IsShuttingDown = true;

client.Close();
client.Dispose();

monitor.Stop();
monitor.Dispose();

availableConnections.Dispose();
}
}
}
2 changes: 1 addition & 1 deletion src/Clients/ExcelClient/ConnectionHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static class ConnectionHelper
{
public static int GetConnectionId(Uri uri)
{
return Convert.ToInt32(uri.ToString().Split('_')[1]);
return Convert.ToInt32(uri.Segments[3].Replace("/", ""));
}

public static string GetConnectionName(Uri uri)
Expand Down
Loading

0 comments on commit dcb0198

Please sign in to comment.