Initial Commit

This commit is contained in:
2016-07-27 00:32:34 -04:00
commit 8d162b2035
701 changed files with 188672 additions and 0 deletions

View File

@@ -0,0 +1,396 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.NetworkInformation;
using Pluto.MSL.Api;
using System.IO;
using Yaulw.Assembly;
namespace MSLConnect
{
[ComVisible(true), Guid("3F04286D-86CF-4C30-85E2-9FF7C0DA9DEB")]
public interface IMSLMobileConnect
{
bool MobileAboutDialog_GotCalled(string SharedConnectionDataSource, string RegisteredName, string PracticeName, string DataBaseNameOrDataSetName, out string UserApiKey, out string UserPin);
bool ProductSetupCompleted_PriorUserLogin(string SharedConnectionDataSource, string RegisteredName);
bool PracticeName_ChangeOccured(string SharedConnectionDataSource, string NewPracticeName, string DataBaseNameOrDataSetName);
bool IsServerReachableFromTheInternet(string SharedConnectionDataSource);
string CheckConnectivity(string SharedConnectionDataSource, string RegisteredName, string PracticeName, string DataBaseNameOrDataSetName);
}
[ComVisible(true), ClassInterface(ClassInterfaceType.None)]
[Guid("803E5D8F-FD6D-4CC8-9DD7-0A2322C565AE")]
public class MSLMobileConnect : IMSLMobileConnect
{
// Hard-coded in * Internal channel always uses this port
internal const int INTERNAL_CHANNEL_PORT = 1945;
// Use this host to check, if we are on the McKesson Network
internal const string MCK_HOST_TO_CHECK_ON_MCK_NETWORK = "ndh1fs01.mckesson.com";
#region Logging
/// <summary>
/// FileWriter Object
/// </summary>
//private Yaulw.File.LoggerQuick _log = null;
/// <summary>
/// Is this DLL running on McKesson Network
/// </summary>
private bool IsRunningOnMcKessonNetwork = false;
private bool DidWeCheckForMcKessonNetwork = false;
/// <summary>
/// Setup the logger upon HasConnectivity Calls, this way it won't be done in the constructor
/// with Medisoft stuff, you just never know
/// </summary>
//private void SetupLoggingIfNotSetup()
//{
// if (!DidWeCheckForMcKessonNetwork)
// {
// IsRunningOnMcKessonNetwork = Yaulw.Net.IPHostHelper.CanResolveHost(MCK_HOST_TO_CHECK_ON_MCK_NETWORK,true);
// DidWeCheckForMcKessonNetwork = true;
// }
// if (_log == null)
// {
// string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\MSLConnect\\";
// _log = new Yaulw.File.LoggerQuick("MSLConnect", IsRunningOnMcKessonNetwork, path);
// }
//}
#endregion
#region Constructor
/// <summary>
/// Construct the beautiful
/// </summary>
public MSLMobileConnect()
{
}
#endregion
#region Connectivity
/// <summary>
/// Check to make sure we can communicate with the Mobile Service.
/// Check the Server's ip & port for connectivity as well as that this
/// computer has connectivity.
/// This way we won't throw any connectivity errors, which is good.
/// </summary>
/// <param name="SharedConnectionDataSource"></param>
/// <remarks>In order for this call to work port INTERNAL_CHANNEL_PORT outgoing must be open,
/// Medisoft, Lytec unified Installer will be responsible for making sure Lytec.exe and MAPA.exe
/// can open up port INTERNAL_CHANNEL_PORT by adding an exception to the windows firewall
/// netsh firewall add allowedprogram \"[Path]\[Program.exe]\" \"[Name]\" ENABLE ALL
/// </remarks>
/// <returns></returns>
private bool HasConnectivity(string SharedConnectionDataSource)
{
//SetupLoggingIfNotSetup();
//_log.Info("HasConnectivity called");
//_log.Debug("With the following SharedConnectionString {0}", SharedConnectionDataSource);
// Retrieve the IP from the DataSource and set it in the API
string host = Yaulw.Net.IPHostHelper.GetServerNameFromAConnectionString(SharedConnectionDataSource);
IPAddress ip = Yaulw.Net.IPHostHelper.GetIpForHost(host);
//_log.Info("Determined the following Host:{0} and IP:{1}", host, ip.ToString());
// Test if we can connect
bool bCanConnect = Yaulw.Net.IPHostHelper.HasConnectivity(SharedConnectionDataSource, INTERNAL_CHANNEL_PORT);
if (bCanConnect)
{
API.SetNetworkSettings(ip.ToString(), INTERNAL_CHANNEL_PORT);
//_log.Info("Network Connectivity to Pluto.MSL Service was established on IP:{0} and Internal Port:{1}", ip, INTERNAL_CHANNEL_PORT);
}
else
{
//_log.Error("Network Connectivity to Pluto.MSL Service could not be established to IP:{0} and Internal Port:{1} HasConnection={2}", ip, INTERNAL_CHANNEL_PORT, Yaulw.Net.IPHostHelper.HasConnection());
}
return bCanConnect;
}
#endregion
#region IMSLMobileConnect
/// <summary>
/// Called by Lytec/Medisoft when the mobile About Dialog is called to retrieve the UserApiKey and Pin
/// </summary>
/// <param name="SharedConnectionDataSource"></param>
/// <param name="PracticeName"></param>
/// <param name="UserApiKey"></param>
/// <param name="UserPin"></param>
/// <returns></returns>
public bool MobileAboutDialog_GotCalled(string SharedConnectionDataSource, string RegisteredName, string PracticeName,string DataBaseNameOrDataSetName, out string UserApiKey, out string UserPin)
{
/* Ensure no nulls */
if(SharedConnectionDataSource == null)
SharedConnectionDataSource = String.Empty;
if(RegisteredName == null)
RegisteredName = String.Empty;
if(PracticeName == null)
PracticeName = String.Empty;
if (DataBaseNameOrDataSetName == null)
DataBaseNameOrDataSetName = String.Empty;
//SetupLoggingIfNotSetup();
//_log.Info("MobileAboutDialog_GotCalled Called");
//_log.Debug("With the following SharedConnectionDataSource:{0},RegisteredName:{1},PracticeName:{2},DataBaseOrDataSetName:{3}", SharedConnectionDataSource, RegisteredName, PracticeName, DataBaseNameOrDataSetName);
UserApiKey = String.Empty;
UserPin = String.Empty;
try
{
if (HasConnectivity(SharedConnectionDataSource))
{
bool bSuccess = API.MobileAboutDialog_GotCalled(SharedConnectionDataSource, RegisteredName, PracticeName, DataBaseNameOrDataSetName, out UserApiKey, out UserPin);
//if(bSuccess)
//_log.Info("MobileAboutDialog_GotCalled returns true");
//else
//_log.Info("MobileAboutDialog_GotCalled returns false");
return bSuccess;
}
}
catch (Exception e)
{
//_log.Error("Exception Thrown {0}", e.Message);
}
//_log.Info("MobileAboutDialog_GotCalled returns false");
return false;
}
/// <summary>
/// Called by Lytec/Medisoft once product setup is complete (product is registered and
/// connected to a database), but before the user logs in. This will setup the Mobile service
/// on the server.
/// </summary>
/// <param name="SharedConnectionDataSource"></param>
/// <param name="RegisteredName"></param>
/// <returns></returns>
public bool ProductSetupCompleted_PriorUserLogin(string SharedConnectionDataSource, string RegisteredName)
{
/* Ensure no nulls */
if (SharedConnectionDataSource == null)
SharedConnectionDataSource = String.Empty;
if (RegisteredName == null)
RegisteredName = String.Empty;
//SetupLoggingIfNotSetup();
//_log.Info("ProductSetupCompleted_PriorUserLogin Called");
//_log.Debug("With the following SharedConnectionDataSource:{0},RegisteredName:{1}", SharedConnectionDataSource, RegisteredName);
try
{
if (HasConnectivity(SharedConnectionDataSource))
{
bool bSuccess = API.ProductSetupCompleted_PriorUserLogin(SharedConnectionDataSource, RegisteredName);
if (bSuccess)
// _log.Info("ProductSetupCompleted_PriorUserLogin returns true");
//else
// _log.Info("ProductSetupCompleted_PriorUserLogin returns false");
return bSuccess;
}
}
catch (Exception e)
{
//_log.Error("Exception Thrown {0}", e.Message);
}
// _log.Info("ProductSetupCompleted_PriorUserLogin returns false");
return false;
}
/// <summary>
/// Called by Lytec/Medisoft after a Practice Name Change occurred on their end to let
/// the Mobile solution know and update it's information
/// </summary>
/// <param name="SharedConnectionDataSource"></param>
/// <param name="NewPracticeName"></param>
/// <returns></returns>
public bool PracticeName_ChangeOccured(string SharedConnectionDataSource, string NewPracticeName, string DataBaseNameOrDataSetName)
{
/* Ensure no nulls */
if (SharedConnectionDataSource == null)
SharedConnectionDataSource = String.Empty;
if (NewPracticeName == null)
NewPracticeName = String.Empty;
if (DataBaseNameOrDataSetName == null)
DataBaseNameOrDataSetName = String.Empty;
//SetupLoggingIfNotSetup();
//_log.Info("PracticeName_ChangeOccured Called");
//_log.Debug("With the following SharedConnectionDataSource:{0},NewPracticeName:{1},DataBaseOrDataSetName:{2}", SharedConnectionDataSource, NewPracticeName, DataBaseNameOrDataSetName);
try
{
if (HasConnectivity(SharedConnectionDataSource))
{
bool bSuccess = API.PracticeName_ChangeOccured(SharedConnectionDataSource, NewPracticeName, DataBaseNameOrDataSetName);
//if (bSuccess)
// _log.Info("PracticeName_ChangeOccured returns true");
//else
// _log.Info("PracticeName_ChangeOccured returns false");
return bSuccess;
}
}
catch (Exception e)
{
// _log.Error("Exception Thrown {0}", e.Message);
}
//_log.Info("PracticeName_ChangeOccured returns false");
return false;
}
/// <summary>
/// Is the Server Reachable from the internet? if not, show error icon or give message
/// </summary>
/// <param name="SharedConnectionDataSource"></param>
/// <returns></returns>
public bool IsServerReachableFromTheInternet(string SharedConnectionDataSource)
{
/* Ensure no nulls */
if (SharedConnectionDataSource == null)
SharedConnectionDataSource = String.Empty;
//SetupLoggingIfNotSetup();
//_log.Info("IsServerReachableFromTheInternet Called");
//_log.Debug("With the following SharedConnectionDataSource:{0}", SharedConnectionDataSource);
try
{
if (HasConnectivity(SharedConnectionDataSource))
{
bool bSuccess = API.IsServerReachableFromTheInternet(SharedConnectionDataSource);
if (bSuccess)
// _log.Info("IsServerReachableFromTheInternet returns true");
//else
// _log.Info("IsServerReachableFromTheInternet returns false");
return bSuccess;
}
}
catch (Exception e)
{
//_log.Error("Exception Thrown {0}", e.Message);
}
//_log.Info("IsServerReachableFromTheInternet returns false");
return false;
}
/// <summary>
/// Checks for CheckConnectivity
/// </summary>
private enum Checks
{
Skipped,
Passed,
Failed
}
/// <summary>
/// Check Connectivity Function simplifies the above calls by summarizing issues that occur when
/// connecting the Mobile Device
/// </summary>
/// <param name="SharedConnectionDataSource"></param>
/// <param name="RegisteredName"></param>
/// <param name="PracticeName"></param>
/// <returns></returns>
public string CheckConnectivity(string SharedConnectionDataSource, string RegisteredName, string PracticeName, string DataBaseNameOrDataSetName)
{
/* Ensure no nulls */
if (SharedConnectionDataSource == null)
SharedConnectionDataSource = String.Empty;
if (RegisteredName == null)
RegisteredName = String.Empty;
if (PracticeName == null)
PracticeName = String.Empty;
if (DataBaseNameOrDataSetName == null)
DataBaseNameOrDataSetName = String.Empty;
// SetupLoggingIfNotSetup();
// _log.Info("CheckConnectivity Called");
//_log.Debug("With the following SharedConnectionDataSource:{0},RegisteredName:{1},PracticeName:{2},DataBaseOrDataSetName:{3}", SharedConnectionDataSource, RegisteredName, PracticeName, DataBaseNameOrDataSetName);
StringBuilder sb = new StringBuilder();
sb.Append("Checking connectivity to 'Mobile Service': {0}\n");
sb.Append("Checking outgoing connectivity: {1}\n");
sb.Append("Checking incoming connectivity: {2}\n");
// 3 Checks
Checks check1 = Checks.Skipped;
Checks check2 = Checks.Skipped;
Checks check3 = Checks.Skipped;
// Check 1
if (ProductSetupCompleted_PriorUserLogin(SharedConnectionDataSource, RegisteredName))
{
check1 = Checks.Passed;
// Check 2
string strUserApiKey;
string strApiPin;
if (MobileAboutDialog_GotCalled(SharedConnectionDataSource, RegisteredName, PracticeName, DataBaseNameOrDataSetName, out strUserApiKey, out strApiPin))
{
check2 = Checks.Passed;
// Check 3
if (IsServerReachableFromTheInternet(SharedConnectionDataSource))
{
check3 = Checks.Passed;
}
else
{
check3 = Checks.Failed;
}
}
else
{
check2 = Checks.Failed;
}
// * Newly Added * Once Check 1 passes we know we can connect to the service,
// so might as well try to update the service, if needed, to make sure they are running the latest
// however let's do it here, at the end, after performing all of our checks
// ~Let's not do this, let them try to connect with their device (this was/is either too clever or
// too silly) after re-consideration, i think it is best to skip
//UpdateServiceIfNeeded(SharedConnectionDataSource);
}
else
{
check1 = Checks.Failed;
}
string retVal = String.Format(sb.ToString(), check1.ToString(), check2.ToString(), check3.ToString());
//_log.Info("CheckConnectivity returns string:{0}", retVal);
return retVal;
}
#endregion
#region Pluto AddOns
/// <summary>
/// Try to Update the Service, if needed
/// </summary>
/// <param name="SharedConnectionDataSource"></param>
/// <returns></returns>
public void UpdateServiceIfNeeded(string SharedConnectionDataSource)
{
//SetupLoggingIfNotSetup();
//_log.Info("UpdateServiceIfNeeded");
//_log.Debug("With the following SharedConnectionDataSource:{0}", SharedConnectionDataSource);
try
{
if (HasConnectivity(SharedConnectionDataSource))
API.UpdateServiceIfNeeded();
}
catch (Exception e)
{
//_log.Error("Exception Thrown {0}", e.Message);
}
}
#endregion
}
}