Major upgrade

This commit is contained in:
Duc
2025-10-24 15:18:11 -07:00
parent fd85735c93
commit ce583d1664
478 changed files with 237518 additions and 47610 deletions

View File

@@ -0,0 +1,75 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System.Collections.Generic;
namespace ProgramLib
{
internal enum TcpClientNames
{
UUT_TEST_PORT
}
/// <summary>
/// Stores global events that any thread can use to wait on
/// </summary>
internal class EthernetSocketManager
{
private Dictionary<TcpClientNames, TcpClient> _tcpClientsDict = new Dictionary<TcpClientNames, TcpClient>();
/// <summary>
/// The private constructor
/// </summary>
public EthernetSocketManager()
{
}
/// <summary>
/// Destructor
/// </summary>
~EthernetSocketManager()
{
foreach (KeyValuePair<TcpClientNames, TcpClient> item in _tcpClientsDict)
{
item.Value.Disconnect();
}
}
/// <summary>
/// Get Tcp Client Socket
/// </summary>
public TcpClient GetTcpClient(TcpClientNames tcpClientName)
{
TcpClient tcpClient = null;
if (_tcpClientsDict.ContainsKey(tcpClientName))
tcpClient = _tcpClientsDict[tcpClientName];
return tcpClient;
}
/// <summary>
/// Add Tcp Client Socket
/// </summary>
public void AddTcpClient(TcpClientNames tcpClientName, TcpClient tcpClient)
{
if (!_tcpClientsDict.ContainsKey(tcpClientName))
_tcpClientsDict[tcpClientName] = tcpClient;
}
}
}

View File

@@ -0,0 +1,152 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace ProgramLib
{
/// <summary>
/// Class that maps event array index to any event enumeration and wraps the WaitHandle.WaitAny() function
/// Use case:
/// When calling WaitHandle.WaitAny(EventArray), it only returns the index of the event in the array that is being signalled.
/// Refering to an index of the array to know which event it is is not ideal. We want to be able to refer to an enumeration instead
/// Usage:
/// In class that uses this class, must define a enumeration
/// public enum Events
/// {
/// EVENT1,
/// EVENT2,
/// EVENT3,
/// EVENTN
///
/// // DO NOT change the name
/// // This must be the last member in the enum
/// EVENT_TIMED_OUT
/// }
/// Dictionary<Events, EventWaitHandle> dict = new Dictionary<Events, EventWaitHandle>();
/// dict[Events.EVENT1] = new ManualResetEvent(false);
/// dict[Events.EVENT2] = new AutoResetEvent(false);
/// dict[Events.EVENT3] = new ManualResetEvent(false);
/// dict[Events.EVENTN] = new AutoResetEvent(false);
/// dict[Events.EVENT_TIMED_OUT] = null;
///
/// EventGroup<Events, EventWaitHandle> eventGroup = new EventGroup<Events, EventWaitHandle>(dict);
///
/// Events id = eventGroup.WaitAny([Optional_timeout]);
///
/// if (id == Events.EVENT_TIMED_OUT){} // only if timeout was specified
/// if (id == Events.EVENT1){}
///
/// </summary>
internal class EventGroup<T1, T2>
{
Dictionary<T1, T2> _eventDict = null;
T2[] _eventArray = null;
/// <summary>
/// Constructor
/// </summary>
private EventGroup()
{
}
/// <summary>
/// Constructor
/// The event enum passed in must be defined in the following format:
/// public enum Events
/// {
/// EVENT1,
/// EVENT2,
/// EVENT3,
/// EVENTN
///
/// // DO NOT change the name
/// // This must be the last member in the enum
/// EVENT_TIMED_OUT
/// }
/// </summary>
/// <param name="eventDict">A dictionary that contains event enum that is associated to an event object</param>
public EventGroup(Dictionary<T1, T2> eventDict)
{
if (eventDict == null)
throw new Exception($"{nameof(eventDict)} cannot be null");
if (!eventDict.First().Key.GetType().IsEnum)
{
throw new Exception($"{nameof(eventDict)}'s key must be an enumerated type");
}
// get the last element in the dictionary
var element = eventDict.ElementAt(eventDict.Count - 1);
// check if the name of the last enum member is what we expect
string actualNameOfLastEnumMember = ((Enum)Convert.ChangeType(element.Key, typeof(Enum))).ToString();
string expectedNameOfLastEnumMember = "EVENT_TIMED_OUT";
if (actualNameOfLastEnumMember != expectedNameOfLastEnumMember)
{
throw new Exception($"Enum {element.Key.GetType().Name} must have {expectedNameOfLastEnumMember} as its last member. {nameof(eventDict)} must have {expectedNameOfLastEnumMember} as the last key in the dictionary");
}
if (eventDict.First().Value.GetType().BaseType != typeof(EventWaitHandle))
{
throw new Exception($"{nameof(eventDict)}'s value must be ManualResetEvent or AutoResetEvent type");
}
_eventDict = eventDict;
_eventArray = new T2[_eventDict.Count - 1];
int index = 0;
foreach (KeyValuePair<T1, T2> entry in _eventDict)
{
if (index < _eventDict.Count - 1)
_eventArray[index++] = entry.Value;
}
}
/// <summary>
/// Return the enumerated event based on the index of the event in the event array that is being signalled
/// </summary>
/// <param name="timeoutMilliseconds">time out in milliseconds</param>
public T1 WaitAny(int? timeoutMilliseconds = null)
{
int index = 0;
T1 eventId = default;
if (timeoutMilliseconds == null)
index = WaitHandle.WaitAny((EventWaitHandle[])Convert.ChangeType(_eventArray, typeof(EventWaitHandle[])));
else
index = WaitHandle.WaitAny((EventWaitHandle[])Convert.ChangeType(_eventArray, typeof(EventWaitHandle[])), (int)timeoutMilliseconds);
if (index == WaitHandle.WaitTimeout)
{
var element = _eventDict.ElementAt(_eventDict.Count - 1);
eventId = element.Key;
}
else
{
var element = _eventDict.ElementAt(index);
eventId = element.Key;
}
return eventId;
}
}
}

View File

@@ -0,0 +1,33 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
namespace ProgramLib
{
/// <summary>
/// Partial class... defines all the types that this class needs
/// </summary>
internal partial class EventManager
{
public enum Events
{
GLOBAL_QUIT,
UUT_POWER_ON,
UUT_POWER_OFF,
FATAL_FAILURE
}
}
}

View File

@@ -0,0 +1,55 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Linq;
using System.Threading;
namespace ProgramLib
{
/// <summary>
/// Stores global events that any thread can use to wait on
/// </summary>
internal partial class EventManager
{
private EventWaitHandle[] _events = new EventWaitHandle[Enum.GetValues(typeof(Events)).Cast<int>().Max() + 1];
/// <summary>
/// The private constructor
/// </summary>
public EventManager()
{
for (int i = 0; i < _events.Count(); i++)
{
_events[i] = new ManualResetEvent(false);
}
}
/// <summary>
/// Implement Indexer to obtain an event object
/// </summary>
/// <param name=""></param>
/// <returns></returns>
public EventWaitHandle this[Events eventId]
{
get
{
return _events[(int)eventId];
}
}
}
}

View File

@@ -0,0 +1,44 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
namespace ProgramLib
{
/// <summary>
/// Partial class... defines all the types that this class needs
/// </summary>
internal partial class FileAndFolderManager
{
public enum Folders
{
// List data folder + its subfolders
DATA,
DATA_GENERAL,
DATA_GENERAL_TEMP,
DATA_TEST,
CONFIG,
CONFIG_MEASUREMENT
}
public enum Files
{
NLOG_TEMP,
CABLE_SELF_TEST_RUN_LOG,
TEST_RUN_LOG
}
}
}

View File

@@ -0,0 +1,227 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using Raytheon.Common;
namespace ProgramLib
{
/// <summary>
/// Partial class... this is the main class responsible for parsing config.ini in order
/// to construct file paths and folder paths
/// </summary>
internal partial class FileAndFolderManager
{
private Dictionary<Folders, string> foldersDict = new Dictionary<Folders, string>();
private Dictionary<Files, string> filesDict = new Dictionary<Files, string>();
private IConfigurationFile _programGeneralConfig;
private IConfigurationFile _programSpecificConfig;
private bool _isThereHardware;
private string _configSubFolderName;
/// <summary>
/// Constructor
/// </summary>
/// <param name="programGeneralConfig">the UUT part number</param>
public FileAndFolderManager(IConfigurationFile programGeneralConfig, out IConfigurationFile programSpecificConfig, bool isThereHardware, string configSubFolderName)
{
_programGeneralConfig = programGeneralConfig;
_isThereHardware = isThereHardware;
_configSubFolderName = configSubFolderName;
ConstructFolderPaths();
CreateFolders();
ConstructFilePaths();
programSpecificConfig = _programSpecificConfig;
}
/// <summary>
/// Destructor
/// </summary>
~FileAndFolderManager()
{
if (foldersDict.ContainsKey(Folders.DATA_TEST))
{
if (Directory.Exists(foldersDict[Folders.DATA_TEST]) && Directory.Exists(foldersDict[Folders.DATA]))
{
// delete all empty test folders
if (foldersDict[Folders.DATA_TEST].Contains(foldersDict[Folders.DATA]))
{
string parentFolder = Path.GetFullPath(Path.Combine(foldersDict[Folders.DATA_TEST], ".."));
while (!String.Equals(parentFolder, foldersDict[Folders.DATA], StringComparison.OrdinalIgnoreCase))
{
string[] dirs = Directory.GetDirectories(parentFolder);
foreach (string dir in dirs)
{
if (Util.IsDirectoryEmpty(dir))
Directory.Delete(dir, true);
}
if (Util.IsDirectoryEmpty(parentFolder))
Directory.Delete(parentFolder, true);
parentFolder = Path.GetFullPath(Path.Combine(parentFolder, ".."));
}
}
}
}
}
public void ConstructTestFolder(UutInfo uutInfo, TestInfo testInfo)
{
string buildLevel = uutInfo.UutBuildLevel.ToString();
if (uutInfo.UutBuildLevel == UutInfo.BuildLevel.NOT_SET)
{
buildLevel = "NO_UUT";
}
foldersDict[Folders.DATA_TEST] = Path.Combine(foldersDict[Folders.DATA], buildLevel, uutInfo.PartNumber,
uutInfo.SerialNumber, testInfo.TestType.ToLower(), testInfo.TestStartDateTime.ToString("yyyy_MM_dd"),
testInfo.TestName, testInfo.TestStartDateTime.ToString("HH_mm_ss"));
CreateFolders();
}
/// <summary>
/// Build folder paths so we can acccess them later
/// </summary>
/// <returns></returns>
private void ConstructFolderPaths()
{
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string configHardwareOrSimSubFolderName = _programGeneralConfig.ReadValue(ProgramGeneralConfigIni.GENERAL.ToString(), ProgramGeneralConfigIni.SIM_CONFIG_FOLDER_NAME.ToString());
if (_isThereHardware)
configHardwareOrSimSubFolderName = _programGeneralConfig.ReadValue(ProgramGeneralConfigIni.GENERAL.ToString(), ProgramGeneralConfigIni.HARDWARE_CONFIG_FOLDER_NAME.ToString());
foldersDict[Folders.CONFIG] = Path.Combine(assemblyFolder, GeneralConstants.ConfigFolderName, configHardwareOrSimSubFolderName, _configSubFolderName);
string measurementConfigFolderName = _programGeneralConfig.ReadValue(ProgramGeneralConfigIni.GENERAL.ToString(), ProgramGeneralConfigIni.MEASUREMENT_CONFIG_FOLDER_NAME.ToString());
foldersDict[Folders.CONFIG_MEASUREMENT] = Path.Combine(foldersDict[Folders.CONFIG], measurementConfigFolderName);
string programSpecificConfigFilePath = Path.Combine(GetFolder(Folders.CONFIG), _programGeneralConfig.ReadValue(ProgramGeneralConfigIni.GENERAL.ToString(), ProgramGeneralConfigIni.PROGRAM_SPECIFIC_CONFIG_FILE_NAME.ToString()));
_programSpecificConfig = new ConfigurationFile(programSpecificConfigFilePath);
string dataRootPath;
// If primary drive exists on machine, all TE software files and folders should be located on that drive
string drive = _programSpecificConfig.ReadValue(ProgramSpecificConfigIni.GENERAL.ToString(), ProgramSpecificConfigIni.PRIMARY_DRIVE.ToString());
if (!Directory.Exists(drive))
{
drive = _programSpecificConfig.ReadValue(ProgramSpecificConfigIni.GENERAL.ToString(), ProgramSpecificConfigIni.SECONDARY_DRIVE.ToString());
}
dataRootPath = Path.Combine(drive, _programSpecificConfig.ReadValue(ProgramSpecificConfigIni.GENERAL.ToString(), ProgramSpecificConfigIni.DATA_BASE_FOLDER.ToString()));
if (!Path.IsPathRooted(dataRootPath))
dataRootPath = Path.Combine(assemblyFolder, dataRootPath);
else
{
Match regexMatch;
regexMatch = Regex.Match(dataRootPath, @"^([a-zA-Z]:\\).+", RegexOptions.IgnoreCase);
if (regexMatch.Success)
{
string driveLetter = regexMatch.Groups[1].Value;
if (!Directory.Exists(driveLetter))
{
string err = $@"Invalid drive: {driveLetter}. Please provide a valid drive, ie C:\. File: {programSpecificConfigFilePath}. Section: {ProgramSpecificConfigIni.GENERAL.ToString()}. Key: {ProgramSpecificConfigIni.PRIMARY_DRIVE.ToString()} and Key: {ProgramSpecificConfigIni.SECONDARY_DRIVE.ToString()} were invalid drives.";
throw new Exception(err);
}
}
else
{
string err = $@"Invalid path: {dataRootPath}. Please specify desired folder name, i.e. Data. File: {programSpecificConfigFilePath}. Section: {ProgramSpecificConfigIni.GENERAL.ToString()}. Key: {ProgramSpecificConfigIni.DATA_BASE_FOLDER.ToString()}";
throw new Exception(err);
}
}
foldersDict[Folders.DATA] = Path.GetFullPath(dataRootPath);
string val = _programSpecificConfig.ReadValue(ProgramSpecificConfigIni.GENERAL.ToString(), ProgramSpecificConfigIni.DATA_GENERAL_FOLDER_NAME.ToString());
foldersDict[Folders.DATA_GENERAL] = Path.Combine(dataRootPath, val);
val = _programSpecificConfig.ReadValue(ProgramSpecificConfigIni.GENERAL.ToString(), ProgramSpecificConfigIni.DATA_GENERAL_TEMP_FOLDER_NAME.ToString());
foldersDict[Folders.DATA_GENERAL_TEMP] = Path.Combine(foldersDict[Folders.DATA_GENERAL], val);
}
/// <summary>
/// We create all the necessary folders
/// </summary>
/// <returns></returns>
private void CreateFolders()
{
// create all the folders if they don't exist
foreach (KeyValuePair<Folders, string> entry in foldersDict)
{
Directory.CreateDirectory(entry.Value);
}
}
/// <summary>
/// Build file paths so we can acccess them later
/// </summary>
/// <returns></returns>
private void ConstructFilePaths()
{
string nlogFileNamePrefix = _programGeneralConfig.ReadValue(ProgramGeneralConfigIni.GENERAL.ToString(), ProgramGeneralConfigIni.NLOG_FILE_NAME_PREFIX.ToString());
filesDict[Files.NLOG_TEMP] = Path.Combine(GetFolder(FileAndFolderManager.Folders.DATA_GENERAL_TEMP), _programGeneralConfig.ReadValue(ProgramGeneralConfigIni.GENERAL.ToString(), ProgramGeneralConfigIni.NLOG_FOLDER_NAME.ToString()), DateTime.Now.ToString("yyyy_MM_dd"), Util.GenerateUniqueFilenameUsingDateTime(nlogFileNamePrefix, "log"));
filesDict[Files.CABLE_SELF_TEST_RUN_LOG] = Path.Combine(GetFolder(FileAndFolderManager.Folders.DATA_GENERAL), _programGeneralConfig.ReadValue(ProgramGeneralConfigIni.GENERAL.ToString(), ProgramGeneralConfigIni.CABLE_SELF_TEST_RUN_LOG_FILE_NAME.ToString()));
filesDict[Files.TEST_RUN_LOG] = Path.Combine(GetFolder(FileAndFolderManager.Folders.DATA_GENERAL), _programGeneralConfig.ReadValue(ProgramGeneralConfigIni.GENERAL.ToString(), ProgramGeneralConfigIni.TEST_RUN_LOG_FILE_NAME.ToString()));
}
/// <summary>
/// Return the full folder path
/// </summary>
/// <param name="folder"></param>
/// <returns></returns>
public string GetFolder(Folders folder)
{
if (foldersDict.ContainsKey(folder))
{
return foldersDict[folder];
}
else
throw new Exception($"{folder.ToString()} is invalid");
}
/// <summary>
/// Return the full file path
/// </summary>
/// <returns></returns>
public string GetFile(Files file)
{
if (filesDict.ContainsKey(file))
{
return filesDict[file];
}
else
throw new Exception($"{file.ToString()} is invalid");
}
}
}

View File

@@ -0,0 +1,29 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
namespace ProgramLib
{
/// <summary>
/// Define non-specific constants
/// </summary>
internal static class GeneralConstants
{
public const string ConfigFolderName = "ConfigFiles";
public const string ProgramGeneralConfigFilename = "ProgramGeneral.ini";
}
}

View File

@@ -0,0 +1,307 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.DirectoryServices;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using NLog;
namespace ProgramLib
{
/// <summary>
/// Provides utility functions for other classes to use
/// </summary>
internal static class Util
{
/// <summary>
/// Check if directory is empty
/// </summary>
public static bool IsDirectoryEmpty(string path)
{
return !Directory.EnumerateFileSystemEntries(path).Any();
}
/// <summary>
/// Generate random fractional part
/// </summary>
public static float GenerateRandomFraction()
{
Random rnd = new Random();
int randNum = 0;
const int minimum = 1;
randNum = rnd.Next(20);
if (randNum <= minimum)
{
randNum += minimum;
}
return (float)(1.0 / (float)randNum);
}
/// <summary>
/// Generate unique file name
/// Format: [Prefix]_YYYY_MM_DD_HH_MM_SS.[ext]
/// </summary>
public static string GenerateUniqueFilenameUsingDateTime(string prefix, string fileExtension)
{
string filename = prefix + "_" + DateTime.Now.ToString("yyyy_MM_dd") + "_" + DateTime.Now.ToString("HH_mm_ss");
if (fileExtension[0] != '.')
{
fileExtension = "." + fileExtension;
}
filename += fileExtension;
return filename;
}
/// <summary>
/// Log Exception
/// </summary>
public static string LogException(Exception ex, ILogger logger)
{
string errorMsg = ex.Message;
string stackTrace = ex.StackTrace;
Exception innerEx = ex.InnerException;
while (innerEx != null)
{
errorMsg = innerEx.Message;
stackTrace = innerEx.StackTrace + "\r\n" + stackTrace;
innerEx = innerEx.InnerException;
}
logger.Error(errorMsg + "\r\n" + stackTrace);
return errorMsg;
}
/// <summary>
/// Auto format any numeric type to string
/// </summary>
/// <param name="wholeNumberMaxDigits">number of digits to display for the whole number before it display in scientific notation</param>
public static string AutoFormatNumberToString<T>(T o, int wholeNumberMaxDigits = 3, int numDecimalPlaces = 2) where T : IConvertible
{
try
{
if (Convert.ChangeType(o, typeof(double)) is double @double)
{
string originalStr = @double.ToString("G"); // Most compact
string tempStr = originalStr;
int indexOfDecimalPoint = tempStr.IndexOf(".");
if (indexOfDecimalPoint == -1)
tempStr += ".0";
indexOfDecimalPoint = tempStr.IndexOf(".");
int tempStrIndex = 0;
int indexOfMinusSign = tempStr.IndexOf("-");
if (indexOfMinusSign != -1)
tempStrIndex = 1;
int wholeNumberNumDigits = tempStr.Substring(tempStrIndex, indexOfDecimalPoint - tempStrIndex).Length;
int fractionalNumDigits = tempStr.Substring(indexOfDecimalPoint + 1, tempStr.Length - (indexOfDecimalPoint + 1)).Length;
if (wholeNumberNumDigits > wholeNumberMaxDigits || tempStr.IndexOf("E") != -1)
{
string decimalPlaces = String.Empty;
for (int i = 1; i <= numDecimalPlaces; i++)
{
decimalPlaces += "#";
}
var custom = @double.ToString($"0.{decimalPlaces}E0").Replace("E+", "E");
while (custom.Contains("E0")) custom = custom.Replace("E0", "E");
while (custom.Contains("-0")) custom = custom.Replace("-0", "-");
if ((@double < 0) && custom[0] != '-')
{
custom.Insert(0, "-");
}
return custom;
}
else if (fractionalNumDigits > numDecimalPlaces)
{
return @double.ToString("0.##");
}
else
{
return originalStr;
}
}
}
catch { }
return o.ToString();
}
/// <summary>
/// Get full name of windows user
/// </summary>
public static string GetWindowsUserFullName(string domain, string userName)
{
string name = "";
try
{
DirectoryEntry userEntry = new DirectoryEntry("WinNT://" + domain + "/" + userName + ",User");
name = (string)userEntry.Properties["fullname"].Value;
}
catch
{
name = userName;
}
return name;
}
/// <summary>
/// Convert struct to byte array
/// </summary>
public static byte[] StructToByteList<T>(T data)
{
int size = Marshal.SizeOf(data);
byte[] arr = new byte[size];
GCHandle h = default(GCHandle);
try
{
h = GCHandle.Alloc(arr, GCHandleType.Pinned);
Marshal.StructureToPtr(data, h.AddrOfPinnedObject(), false);
}
finally
{
if (h.IsAllocated)
{
h.Free();
}
}
return arr;
}
/// <summary>
/// Convert byte array to struct
/// </summary>
public static T ByteArrayToStruct<T>(byte[] array)
{
object obj;
GCHandle h = default(GCHandle);
try
{
h = GCHandle.Alloc(array, GCHandleType.Pinned);
obj = Marshal.PtrToStructure(h.AddrOfPinnedObject(), typeof(T));
}
finally
{
if (h.IsAllocated)
{
h.Free();
}
}
return (T)obj;
}
/// <summary>
/// Get Two's Compliment Checksum
/// </summary>
public static byte GetTwosComplimentChecksum(byte[] array)
{
return (byte)(0x100u - ComputeSum(array));
}
/// <summary>
/// Add up all bytes in a byte array
/// </summary>
public static byte ComputeSum(byte[] array)
{
byte sum = 0;
for (int i = 0; i < array.Length; i++)
sum += array[i];
return sum;
}
/// <summary>
/// Display each byte in byte array as hex string
/// </summary>
public static string ByteArrayToHexString(byte[] bytes, int numBytes = -1)
{
StringBuilder Result = new StringBuilder(bytes.Length * 2);
string HexAlphabet = "0123456789ABCDEF";
if (numBytes < 1)
{
numBytes = bytes.Length;
}
for (int i = 0; i < numBytes; i++)
{
Result.Append("0x" + HexAlphabet[(int)(bytes[i] >> 4)]);
Result.Append(HexAlphabet[(int)(bytes[i] & 0xF)] + " ");
}
return Result.ToString();
}
/// <summary>
/// Given a variable of type TimeSpan, describe the time in days, hours, mins, seconds
/// </summary>
public static string DescribeTimeElapsed(TimeSpan ts)
{
string describe = "";
if (ts.Days > 0)
describe += ts.Days.ToString() + " d";
if (ts.Hours > 0)
{
if (describe.Length > 0)
describe += " ";
describe += ts.Hours.ToString() + " h";
}
if (ts.Minutes > 0)
{
if (describe.Length > 0)
describe += " ";
describe += ts.Minutes.ToString() + " m";
}
if (ts.Seconds > 0)
{
if (describe.Length > 0)
describe += " ";
describe += ts.Seconds.ToString() + " s";
}
if (describe.Length == 0)
describe = "0 s";
return describe;
}
}
}

View File

@@ -0,0 +1,237 @@
/*-------------------------------------------------------------------------
// UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
namespace ProgramLib
{
/// <summary>
/// A XML Wrapper class to create/modify XML files
/// </summary>
internal class XmlDocumentWrapper
{
public enum AddNodePosition
{
First,
Last
}
private XmlDocument _xmlDoc = null;
private string _xmlFilePath = String.Empty;
private object _syncObj = new object();
/// <summary>
/// Constructor
/// </summary>
/// <param name="xmlFilePath">XML file path</param>
/// <param name="rootNodeName">name of the root node.</param>
public XmlDocumentWrapper(string xmlFilePath, string rootNodeName = "root")
{
_xmlFilePath = xmlFilePath;
CreateXmlDocument(rootNodeName);
_xmlDoc = new XmlDocument();
_xmlDoc.Load(xmlFilePath);
}
/// <summary>
/// Create XML document if it doesn't exist
/// </summary>
private void CreateXmlDocument(string rootNodeName)
{
if (!File.Exists(_xmlFilePath))
{
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement(rootNodeName);
doc.AppendChild(root);
using (TextWriter sw = new StreamWriter(_xmlFilePath, false, Encoding.UTF8))
{
doc.Save(sw);
}
}
}
/// <summary>
/// Save XML document to file
/// </summary>
public void SaveToFile()
{
lock (_syncObj)
{
using (TextWriter sw = new StreamWriter(_xmlFilePath, false, Encoding.UTF8))
{
_xmlDoc.Save(sw);
}
}
}
/// <summary>
/// Add a node defined by {path}
/// </summary>
/// <param name="path">example: /root/node1/node2</param>
/// <param name="attributesDict">a dictionary of [name,value] pairs</param>
/// <param name="innerText">text of the node</param>
public void AddNode(string path, Dictionary<string, string> attributesDict = null, string innerText = null, AddNodePosition addNodePosition = AddNodePosition.Last)
{
lock (_syncObj)
{
XmlElement elem = (XmlElement)MakeXPath(_xmlDoc, path, addNodePosition);
if (!String.IsNullOrEmpty(innerText))
elem.InnerText = innerText;
if (attributesDict != null)
{
List<XmlAttribute> attributes = new List<XmlAttribute>();
foreach (KeyValuePair<string, string> item in attributesDict)
{
XmlAttribute attr = _xmlDoc.CreateAttribute(item.Key);
attr.Value = item.Value;
attributes.Add(attr);
}
SetAttrSafe(elem, attributes.ToArray());
}
}
}
/// <summary>
/// Remove a node
/// </summary>
public void RemoveNode(XmlNode node)
{
lock (_syncObj)
{
node.ParentNode.RemoveChild(node);
}
}
/// <summary>
/// Change attributes and/or inner text of an existing node
/// </summary>
public void ChangeNode(XmlNode node, Dictionary<string, string> attributesDict = null, string innerText = null)
{
lock (_syncObj)
{
if (!String.IsNullOrEmpty(innerText))
node.InnerText = innerText;
if (attributesDict != null)
{
List<XmlAttribute> attributes = new List<XmlAttribute>();
foreach (KeyValuePair<string, string> item in attributesDict)
{
XmlAttribute attr = _xmlDoc.CreateAttribute(item.Key);
attr.Value = item.Value;
attributes.Add(attr);
}
SetAttrSafe(node, attributes.ToArray());
}
}
}
/// <summary>
/// Get the first node in {path}
/// Useful for iterating through the sibling nodes to find the node with a specific attribute so we can modify the node
/// </summary>
/// <param name="path">example: /root/node1/node2</param>
public XmlNode GetNode(string path)
{
lock (_syncObj)
{
return _xmlDoc.SelectSingleNode(path);
}
}
/// <summary>
/// Get all the nodes matching the path
/// Useful for iterating through the matched nodes
/// </summary>
/// <param name="path">example: /root/node1/node2</param>
public XmlNodeList GetNodes(string path)
{
lock (_syncObj)
{
return _xmlDoc.SelectNodes(path);
}
}
/// <summary>
/// Set attribute
/// </summary>
private void SetAttrSafe(XmlNode node, XmlAttribute[] attrList)
{
foreach (var attr in attrList)
{
if (node.Attributes[attr.Name] != null)
{
node.Attributes[attr.Name].Value = attr.Value;
}
else
{
node.Attributes.Append(attr);
}
}
}
/// <summary>
/// Add a node using {xpath}
/// </summary>
/// <param name="xpath">example: /root/node1/node2</param>
private XmlNode MakeXPath(XmlDocument doc, string xpath, AddNodePosition addNodePosition)
{
return MakeXPath(doc, doc as XmlNode, xpath, addNodePosition);
}
/// <summary>
/// Iterate through each node in {xpath} and create them
/// </summary>
private XmlNode MakeXPath(XmlDocument doc, XmlNode parent, string xpath, AddNodePosition addNodePosition)
{
// grab the next node name in the xpath; or return parent if empty
string[] partsOfXPath = xpath.Trim('/').Split('/');
string nextNodeInXPath = partsOfXPath.First();
if (string.IsNullOrEmpty(nextNodeInXPath))
return parent;
// get or create the node from the name
XmlNode node = parent.SelectSingleNode(nextNodeInXPath);
if (partsOfXPath.Length == 1)
{
if (addNodePosition == AddNodePosition.Last)
node = parent.AppendChild(doc.CreateElement(nextNodeInXPath));
else
node = parent.PrependChild(doc.CreateElement(nextNodeInXPath));
}
// rejoin the remainder of the array as an xpath expression and recurse
string rest = String.Join("/", partsOfXPath.Skip(1).ToArray());
return MakeXPath(doc, node, rest, addNodePosition);
}
}
}