initial checkin of yaulw (locally)
This commit is contained in:
70
@integrate/AlternateDataStreamWrapper.cs
Normal file
70
@integrate/AlternateDataStreamWrapper.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using PhoneHome.Lib.Assembly;
|
||||
|
||||
// Downloaded from
|
||||
// http://www.codeproject.com/Articles/2670/Accessing-alternative-data-streams-of-files-on-an
|
||||
using Trinet.Core.IO.Ntfs;
|
||||
using System.IO;
|
||||
|
||||
namespace PhoneHome
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper class arround Alternate Data Streams
|
||||
/// * IMP * Registrate 'Later' Medisoft Demo Registration Work-arround
|
||||
/// Medisoft has a 30 day trial where they don't enter a serial number. However, this can
|
||||
/// be bypassed, since registration is terrible at what it does. So we must make sure that
|
||||
/// the 30 days haven't passed, and we deal with it here with PhoneHome via AlternateStreams
|
||||
/// </summary>
|
||||
internal static class AlternateDataStreamWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// Read the Timestamp found in the Alternative Stream
|
||||
/// </summary>
|
||||
/// <returns>Dt found or DT.Min (if none found)</returns>
|
||||
internal static DateTime ReadDateTimeStamp()
|
||||
{
|
||||
try
|
||||
{
|
||||
string s_curDir = Path.GetDirectoryName(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileNameNPath(AssemblyW.AssemblyST.Executing));
|
||||
SafeNativeMethods.Win32StreamInfo s_streamInfo = new SafeNativeMethods.Win32StreamInfo() { StreamAttributes = FileStreamAttributes.None, StreamName = "phdt", StreamSize = 20, StreamType = FileStreamType.Data };
|
||||
|
||||
AlternateDataStreamInfo adataStream = new AlternateDataStreamInfo(s_curDir, s_streamInfo);
|
||||
using (FileStream fs = adataStream.OpenRead())
|
||||
using (StreamReader sr = new StreamReader(fs))
|
||||
{
|
||||
string strLine = sr.ReadLine();
|
||||
DateTime dtFound = DateTime.Parse(strLine);
|
||||
return dtFound;
|
||||
}
|
||||
}
|
||||
catch (Exception e) { string Message = e.Message; }
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the passed in Timestamp to the Alternative Stream
|
||||
/// </summary>
|
||||
/// <param name="dtStamp">Timestamp to write</param>
|
||||
internal static void WriteDateTimeStamp(DateTime dtStamp)
|
||||
{
|
||||
try
|
||||
{
|
||||
string s_curDir = Path.GetDirectoryName(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileNameNPath(AssemblyW.AssemblyST.Executing));
|
||||
SafeNativeMethods.Win32StreamInfo s_streamInfo = new SafeNativeMethods.Win32StreamInfo() { StreamAttributes = FileStreamAttributes.None, StreamName = "phdt", StreamSize = 20, StreamType = FileStreamType.Data };
|
||||
|
||||
AlternateDataStreamInfo adataStream = new AlternateDataStreamInfo(s_curDir, s_streamInfo);
|
||||
using (FileStream fs = adataStream.OpenWrite())
|
||||
using (StreamWriter sw = new StreamWriter(fs))
|
||||
{
|
||||
sw.WriteLine(dtStamp.ToShortDateString());
|
||||
}
|
||||
}
|
||||
catch (Exception e) { string Message = e.Message; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
839
@integrate/App.xaml.cs
Normal file
839
@integrate/App.xaml.cs
Normal file
@@ -0,0 +1,839 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Watchdog.WatchdogLib.File;
|
||||
using WatchdogLib.Tools;
|
||||
using Watchdog.WatchdogLib.Process;
|
||||
using Watchdog.WatchdogLib.WinForms;
|
||||
using Watchdog.WatchdogLib.Assembly;
|
||||
using WatchdogLib.File;
|
||||
using System.Reflection;
|
||||
using Watchdog.WatchdogLib.Other;
|
||||
using Watchdog.WatchdogLib.Monitor;
|
||||
using System.Diagnostics;
|
||||
using Forms = System.Windows.Forms;
|
||||
using Watchdog.WatchdogLib.Net;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
||||
namespace Watchdog
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
/// <summary>
|
||||
/// Main Application Object
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
|
||||
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
|
||||
}
|
||||
|
||||
#region Application Constants
|
||||
|
||||
// Application Constants
|
||||
internal static readonly string APPLICATION_NAME_SHORT = AppResx.GetString("APPLICATION_NAME_SHORT");
|
||||
internal static readonly string APPLICATION_NAME_LONG = AppResx.GetString("APPLICATION_NAME_LONG");
|
||||
internal static readonly string SUPPORT_PHONENUMBER = AppResx.GetString("SUPPORT_PHONENUMBER");
|
||||
internal static readonly int APPLICATION_VERSION_MAJOR = AssemblyW.GetAssemblyVersion(AssemblyW.AssemblyST.Executing).Major;
|
||||
internal static readonly int APPLICATION_VERSION_MINOR = AssemblyW.GetAssemblyVersion(AssemblyW.AssemblyST.Executing).Minor;
|
||||
internal static readonly int APPLICATION_VERSION_BUILDNUMBER = AssemblyW.GetAssemblyVersion(AssemblyW.AssemblyST.Executing).Build;
|
||||
internal static readonly int APPLICATION_VERSION_REVISION = AssemblyW.GetAssemblyVersion(AssemblyW.AssemblyST.Executing).Revision;
|
||||
internal static string APPLICATION_VERSION { get { return (APPLICATION_VERSION_MAJOR.ToString() + "." + APPLICATION_VERSION_MINOR.ToString() + "." + APPLICATION_VERSION_BUILDNUMBER.ToString() + "." + APPLICATION_VERSION_REVISION.ToString()); } }
|
||||
|
||||
/// <summary>
|
||||
/// This is the Product ID Generated for our Product via ClickOnce and our Certificate.
|
||||
/// As long as the Certificate Stays the same This ID stays the same.
|
||||
/// ~we are using this to overide the uninstall icon in Add/Remove * Branding *
|
||||
/// </summary>
|
||||
internal static readonly string APPLICATION_PRODUCT_CLICKONCE_ID = "6f02138d8632343a";
|
||||
internal static readonly string APPLICATION_PRODUCT_CLICKONCE_URL = "http://www.medisoft.com/Watchdog/Publish/Watchdog.application";
|
||||
internal static string APPLICATION_CLICKONCE_PUBLISHER { get { return AssemblyW.GetAssemblyCompany(AssemblyW.AssemblyST.Executing); } }
|
||||
internal static string APPLICATION_CLICKONCE_PRODUCT { get { return AssemblyW.GetAssemblyProductName(AssemblyW.AssemblyST.Executing); } }
|
||||
internal static string APPLICATION_CLICKONCE_STARTMENU_LINK
|
||||
{
|
||||
get { return string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "\\", APPLICATION_CLICKONCE_PUBLISHER, "\\", APPLICATION_CLICKONCE_PRODUCT , ".appref-ms"); }
|
||||
}
|
||||
|
||||
// Default Log File Settings
|
||||
internal const int LOG_FILE_FILE_SIZE_IN_MB = 2;
|
||||
internal const int LOG_FILE_NUM_OF_BACKUPS = 4;
|
||||
|
||||
// Log File Constants
|
||||
internal static readonly string FILE_EXTENSION_LOG_DEFAULT = AppResx.GetString("FILE_EXTENSION_LOG_DEFAULT");
|
||||
internal static readonly string LOG_NAME_APPMAIN = AppResx.GetString("APPLICATION_NAME_SHORT");
|
||||
|
||||
// Application Files / Dependencies
|
||||
internal static string APP_LOG_FILENAME { get { return (LOG_NAME_APPMAIN + "." + FILE_EXTENSION_LOG_DEFAULT); } }
|
||||
internal static string APP_LOG_FILENAMEANDPATH
|
||||
{
|
||||
get
|
||||
{
|
||||
// Make sure Subpath begin|end with a slash, as needed
|
||||
string commondir = PathNaming.PathEndsWithSlash(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
|
||||
string subpath = PathNaming.PathBeginsWithNoSlash(PathNaming.PathEndsWithSlash(AppResx.GetString("LOG_FILE_SUBPATH")));
|
||||
string filename = LOG_NAME_APPMAIN + "." + FILE_EXTENSION_LOG_DEFAULT;
|
||||
return (commondir + subpath + filename);
|
||||
}
|
||||
}
|
||||
internal static string APP_LOG_PATH
|
||||
{
|
||||
get
|
||||
{
|
||||
// Make sure Subpath begin|end with a slash, as needed
|
||||
string commondir = PathNaming.PathEndsWithSlash(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
|
||||
string subpath = PathNaming.PathBeginsWithNoSlash(PathNaming.PathEndsWithNoSlash(AppResx.GetString("LOG_FILE_SUBPATH")));
|
||||
return (commondir + subpath);
|
||||
}
|
||||
}
|
||||
internal static string APP_XML_DS_FILENAME { get { return AppResx.GetString("XMLCONFIG_FILENAME"); } }
|
||||
internal static string APP_XML_DS_FILENAMEANDPATH
|
||||
{
|
||||
get
|
||||
{
|
||||
// Make sure Subpath begin|end with a slash, as needed
|
||||
string commondir = PathNaming.PathEndsWithSlash(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
|
||||
string subpath = PathNaming.PathBeginsWithNoSlash(PathNaming.PathEndsWithSlash(AppResx.GetString("XMLCONFIG_FILE_SUBPATH")));
|
||||
string filename = AppResx.GetString("XMLCONFIG_FILENAME");
|
||||
return (commondir + subpath + filename);
|
||||
}
|
||||
}
|
||||
internal static string APP_XML_DS_PATH
|
||||
{
|
||||
get
|
||||
{
|
||||
// Make sure Subpath begin|end with a slash, as needed
|
||||
string commondir = PathNaming.PathEndsWithSlash(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
|
||||
string subpath = PathNaming.PathBeginsWithNoSlash(PathNaming.PathEndsWithNoSlash(AppResx.GetString("XMLCONFIG_FILE_SUBPATH")));
|
||||
return (commondir + subpath);
|
||||
}
|
||||
}
|
||||
internal static string APP_INI_SETTINGS_FILENAME { get { return AppResx.GetString("INISETTINGS_FILENAME"); } }
|
||||
internal static string APP_INI_SETTINGS_FILENAMEANDPATH
|
||||
{
|
||||
get
|
||||
{
|
||||
// Make sure Subpath begin|end with a slash, as needed
|
||||
string commondir = PathNaming.PathEndsWithSlash(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
|
||||
string subpath = PathNaming.PathBeginsWithNoSlash(PathNaming.PathEndsWithSlash(AppResx.GetString("INISETTINGS_SUBPATH")));
|
||||
string filename = AppResx.GetString("INISETTINGS_FILENAME");
|
||||
return (commondir + subpath + filename);
|
||||
}
|
||||
}
|
||||
internal static string APP_INI_SETTINGS_PATH
|
||||
{
|
||||
get
|
||||
{
|
||||
// Make sure Subpath begin|end with a slash, as needed
|
||||
string commondir = PathNaming.PathEndsWithSlash(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
|
||||
string subpath = PathNaming.PathBeginsWithNoSlash(PathNaming.PathEndsWithNoSlash(AppResx.GetString("INISETTINGS_SUBPATH")));
|
||||
return (commondir + subpath);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application Help
|
||||
|
||||
// Application's Main Help Object
|
||||
internal static CHMFile chmhelp = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Xml Configuration
|
||||
|
||||
// Application's Main Xml Object
|
||||
internal static MonitorDataStore xmlfile = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ini Configuration
|
||||
|
||||
// Application's Main Ini Object
|
||||
internal static INIFile inifile = new INIFile(APP_INI_SETTINGS_FILENAMEANDPATH, typeof(Ini_Setting));
|
||||
|
||||
internal enum Ini_Setting
|
||||
{
|
||||
MonitorSettings__Start_With_Windows,
|
||||
MonitorSettings__Monitor_On_Start,
|
||||
MonitorSettings__Max_Fail_Count,
|
||||
MonitorSettings__Max_Fail_Count_Per_Hour,
|
||||
MonitorSettings__Default_Exe_Running_Filter,
|
||||
MonitorSettings__Default_Services_Names_Running_Filter,
|
||||
MonitorSettings__Sheduler_StartDateTime,
|
||||
MonitorSettings__Sheduler_RepeatEveryNHoursOrMinutes,
|
||||
MonitorSettings__Sheduler_RepeatIsHour,
|
||||
MonitorSettings__Sheduler_LastRun_DateTime,
|
||||
MonitorSettings__Scheduler_Restarts_Services,
|
||||
MonitorSettings__ShedulerBackup_StartDateTime,
|
||||
MonitorSettings__ShedulerBackup_ForDurationNHoursOrMinutes,
|
||||
MonitorSettings__ShedulerBackup_DurationIsHour,
|
||||
MonitorSettings__ShedulerBackup_LastRun_DateTime,
|
||||
MonitorSettings__ShedulerBackup_StopInsteadOfPause,
|
||||
MonitorSettings__ShedulerBackup_StopServices,
|
||||
WindowSettings__AboutWindow_TopLeft,
|
||||
WindowSettings__SettingsWindow_TopLeft,
|
||||
WindowSettings__LogViewerWindow_TopLeft,
|
||||
WindowsSettings__LockWorkstation_With_Windows,
|
||||
WindowsSettings__AutoLogin_With_Windows,
|
||||
WindowsSettings__CreateExeHardLink_In_RootPath,
|
||||
EmailSettings__EnableEmailNotifications,
|
||||
EmailSettings__SmtpServer,
|
||||
EmailSettings__SenderEmail,
|
||||
EmailSettings__ReveiverEmail,
|
||||
EmailSettings__SmtpPort,
|
||||
EmailSettings__SmtpRequiresAuth,
|
||||
EmailSettings__SmtpRequiresSSL,
|
||||
EmailSettings__SmtpUsername,
|
||||
EmailSettings__SmtpPassword,
|
||||
EmailSettings__Custom_Message_Text,
|
||||
}
|
||||
|
||||
// Wrapper class arround Ini Settings
|
||||
internal static Settings setting = new Settings();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Command Line Parameters
|
||||
|
||||
// Application's CmdLine Parser
|
||||
internal static CMDline cmdline = new CMDline(typeof(App.CommandLine_Option), typeof(App.CommandLine_Flag));
|
||||
|
||||
/// <summary>
|
||||
/// CommandLine Flags for Application
|
||||
/// </summary>
|
||||
public enum CommandLine_Flag
|
||||
{
|
||||
START,
|
||||
PAUSE,
|
||||
RESTART,
|
||||
RESTART_ALL,
|
||||
STOP,
|
||||
STOP_ALL,
|
||||
SHOW_PROCESSES,
|
||||
SHOW_SERVICES,
|
||||
LOCK,
|
||||
RUNASSERVICE,
|
||||
UNINSTALL,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CommandLine Options for Application
|
||||
/// </summary>
|
||||
public enum CommandLine_Option
|
||||
{
|
||||
ADD_SERVICE,
|
||||
REMOVE_SERVICE,
|
||||
ADD_PROCESS,
|
||||
REMOVE_PROCESS,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Logging Configuration
|
||||
|
||||
// Application's Main Log Object
|
||||
internal static Logging log = null;
|
||||
|
||||
/// <summary>
|
||||
/// Create a Logging_Configuration Object with Default Application Settings
|
||||
/// </summary>
|
||||
/// <param name="LogFileNameNPath">Specify the LogFile and Path to Log to</param>
|
||||
/// <param name="Detail">Specify Logging Details Setting</param>
|
||||
/// <param name="UseExclusiveFileLock">true, to only allow exclusive (one process) access to file</param>
|
||||
/// <returns>a Logging_Configuration object to use Utilities.GenericUtilities.File.Logging</returns>
|
||||
//private static Logging_Configuration CreateDefaultLoggingConfiguration(string LogFileNameNPath, Logging_Detail Detail = Logging_Detail.ERROR, bool UseExclusiveFileLock = false)
|
||||
private static Logging_Configuration CreateDefaultLoggingConfiguration(string LogFileNameNPath, Logging_Detail Detail, bool UseExclusiveFileLock)
|
||||
{
|
||||
Logging_Configuration config;
|
||||
config.LogFileNameNPath = LogFileNameNPath;
|
||||
config.maxFileSizeInMB = LOG_FILE_FILE_SIZE_IN_MB;
|
||||
config.numOfBackupLogFiles = LOG_FILE_NUM_OF_BACKUPS;
|
||||
config.Detail = Detail;
|
||||
config.UseExclusiveFileLock = UseExclusiveFileLock;
|
||||
return config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for creating the AppMain Logging Object
|
||||
/// </summary>
|
||||
public static Logging CreateAppMainLogging()
|
||||
{
|
||||
// Log FileNameNPath * Debug mode set logging level to Debug, Release to Info *
|
||||
#if DEBUG
|
||||
return Logging.AddGlobalLoggerConfiguration(LOG_NAME_APPMAIN, CreateDefaultLoggingConfiguration(APP_LOG_FILENAMEANDPATH, Logging_Detail.DEBUG, false));
|
||||
#else
|
||||
return Logging.AddGlobalLoggerConfiguration(LOG_NAME_APPMAIN, CreateDefaultLoggingConfiguration(APP_LOG_FILENAMEANDPATH, Logging_Detail.INFO, false));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the AppMain Logging Object, It must have been created by calling CreateAppMainLogging()
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Logging GetAppMainLogging()
|
||||
{
|
||||
return Logging.GetLogger(LOG_NAME_APPMAIN);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Message Box Configuration
|
||||
|
||||
/// <summary>
|
||||
/// We also want to initialize the MsgBox Class here
|
||||
/// </summary>
|
||||
public static void ConfigureAppMainMsgBox()
|
||||
{
|
||||
// Fatal Errors
|
||||
MsgBox.MsgBox_FatalErrorTitleHeader = AppResx.GetStringFormated("APPLICATION_FATAL_ERROR", APPLICATION_NAME_SHORT);
|
||||
MsgBox.MsgBox_FatalErrorHeader = AppResx.GetString("FATAL_ERROR_HEADER");
|
||||
MsgBox.MsgBox_FatalErrorFooter = AppResx.GetStringFormated("FATAL_ERROR_APPLICATION_WILL_EXIT", APPLICATION_NAME_LONG) +
|
||||
AppResx.GetStringFormated("CONTACT_SUPPORT_URGENTLY", SUPPORT_PHONENUMBER) +
|
||||
AppResx.GetStringFormated("ERROR_LOG_FILE_LOCATION", APP_LOG_FILENAME, APP_LOG_PATH);
|
||||
|
||||
// Errors
|
||||
MsgBox.MsgBox_ErrorTitleHeader = AppResx.GetStringFormated("APPLICATION_ERROR", APPLICATION_NAME_SHORT);
|
||||
MsgBox.MsgBox_ErrorHeader = AppResx.GetString("ERROR_HEADER");
|
||||
MsgBox.MsgBox_ErrorFooter = AppResx.GetStringFormated("CONTACT_SUPPORT_NICELY", SUPPORT_PHONENUMBER) +
|
||||
AppResx.GetStringFormated("ERROR_LOG_FILE_LOCATION", APP_LOG_FILENAME, APP_LOG_PATH);
|
||||
|
||||
// Info
|
||||
MsgBox.MsgBox_InfoTitleHeader = AppResx.GetStringFormated("APPLICATION_INFO", APPLICATION_NAME_SHORT);
|
||||
|
||||
// * For Debugging *
|
||||
//MsgBox.ShowError("01234567890123456789012345678901234567890123456789012345678901234");
|
||||
//MsgBox.ShowFatalError("01234567890123456789012345678901234567890123456789012345678901234");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application State
|
||||
|
||||
/// <summary>
|
||||
/// Various Keys that we can use to save/get the GUI State
|
||||
/// </summary>
|
||||
internal enum StateKey
|
||||
{
|
||||
Monitor_Started_bool,
|
||||
Monitor_ErrorsOccured_bool,
|
||||
Scheduler_Started_bool,
|
||||
SchedulerBackup_Started_bool,
|
||||
SpecialMode_Paused_Mode_bool,
|
||||
SpecialMode_CommandLine_Mode_bool,
|
||||
SpecialMode_RunAsService_Mode_bool,
|
||||
SpecialCircum_CommandLine_ConsoleWindowIsAttached_bool,
|
||||
SpecialCircum_CommandLine_MonitorInstanceExists_bool,
|
||||
SpecialCircum_DontCloseApplicationsOnExit_bool,
|
||||
Help_Is_Available_bool,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// State of the System
|
||||
/// </summary>
|
||||
public enum StateSystem
|
||||
{
|
||||
Running,
|
||||
Paused,
|
||||
Stopped,
|
||||
Error
|
||||
}
|
||||
|
||||
// Initialize BkgdState
|
||||
internal static readonly StateM State = new StateM(typeof(StateKey));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application State - Monitor State
|
||||
|
||||
/// <summary>
|
||||
/// Returns the state of the System (icon to display)
|
||||
/// </summary>
|
||||
/// <returns>Application State for System</returns>
|
||||
internal static StateSystem State_GetSystemState()
|
||||
{
|
||||
if (State.GetStateValue<bool>(App.StateKey.Monitor_Started_bool, false))
|
||||
{
|
||||
// Error and Pause are Special 'Running' States
|
||||
if (State.GetStateValue<bool>(App.StateKey.SpecialMode_Paused_Mode_bool, false))
|
||||
return StateSystem.Paused;
|
||||
if (State.GetStateValue<bool>(App.StateKey.Monitor_ErrorsOccured_bool, false))
|
||||
return StateSystem.Error;
|
||||
else
|
||||
return StateSystem.Running;
|
||||
}
|
||||
else
|
||||
{
|
||||
return StateSystem.Stopped;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the Monitor Currently in a 'Running' State
|
||||
/// </summary>
|
||||
/// <returns>true if yes, false otherwise</returns>
|
||||
internal static bool State_MonitorIsInRunningState() { return State.GetStateValue<bool>(App.StateKey.Monitor_Started_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the System into an Error State
|
||||
/// </summary>
|
||||
/// <param name="strCustomErrorMessageToNotify">Error Message to Notify to User</param>
|
||||
internal static void State_Error_SetErrorState(string strErrorMessageToNotify)
|
||||
{
|
||||
App.State.SetStateValue<bool>(App.StateKey.Monitor_ErrorsOccured_bool, true);
|
||||
if (!String.IsNullOrEmpty(strErrorMessageToNotify))
|
||||
{
|
||||
////
|
||||
// Application entered an Error State * Better Notify User, if specified *
|
||||
////
|
||||
if (App.setting.EmailNotificationEnabled && App.setting.EmailSettingsValid)
|
||||
{
|
||||
bool bIsSend = Emailer.SendEmail(App.setting.EmailStmpServer, App.setting.EmailSenderEmail, App.APPLICATION_NAME_SHORT,
|
||||
App.setting.EmailReceiverEmail, AppResx.GetStringFormated("ERRORSTATE_EMAIL_SUBJECT", App.APPLICATION_NAME_SHORT),
|
||||
AppResx.GetStringFormated("ERRORSTATE_EMAIL_BODY", App.APPLICATION_NAME_SHORT, strErrorMessageToNotify ,App.setting.EmailCustomMessageText),
|
||||
App.setting.EmailSmtpPort, String.Empty, App.setting.EmailStmpServerRequiresAuth, App.setting.EmailSmtpUsername, App.setting.EmailSmtpPassword,
|
||||
App.setting.EmailStmpServerRequiresSSL, 30);
|
||||
if (!bIsSend)
|
||||
App.log.Error("Failed to Send ERRORSTATE_EMAIL");
|
||||
else
|
||||
App.log.Info(String.Format("Email (ERRORSTATE_EMAIL) Notification send to {0}", App.setting.EmailReceiverEmail));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Error State Reset
|
||||
/// </summary>
|
||||
internal static void State_Error_ResetErrorState() { App.State.SetStateValue<bool>(App.StateKey.Monitor_ErrorsOccured_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Set Main Monitor to Started
|
||||
/// </summary>
|
||||
internal static void State_MonitorStarted() { App.State.SetStateValue<bool>(App.StateKey.Monitor_Started_bool, true); App.State.SetStateValue<bool>(App.StateKey.SpecialMode_Paused_Mode_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Set Main Monitor to Stopped
|
||||
/// </summary>
|
||||
internal static void State_MonitorStopped() { App.State.SetStateValue<bool>(App.StateKey.Monitor_Started_bool, false); App.State.SetStateValue<bool>(App.StateKey.SpecialMode_Paused_Mode_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Set Main Monitor to Paused
|
||||
/// </summary>
|
||||
internal static void State_MonitorPaused() { App.State.SetStateValue<bool>(App.StateKey.SpecialMode_Paused_Mode_bool, true); }
|
||||
|
||||
/// <summary>
|
||||
/// Is the System in a Paused State?
|
||||
/// </summary>
|
||||
/// <returns>true if yes, false if no</returns>
|
||||
internal static bool State_IsMonitorPaused() { return App.State.GetStateValue<bool>(App.StateKey.SpecialMode_Paused_Mode_bool, false); }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application State - Scheduler State
|
||||
|
||||
/// <summary>
|
||||
/// Is the Scheduler Executing?
|
||||
/// </summary>
|
||||
/// <returns>true if yes, false if no</returns>
|
||||
internal static bool State_IsSchedulerExecuting() { return App.State.GetStateValue<bool>(App.StateKey.Scheduler_Started_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Scheduler Execution Started
|
||||
/// </summary>
|
||||
internal static void State_SchedulerExecution_Started() { App.State.SetStateValue<bool>(App.StateKey.Scheduler_Started_bool, true); }
|
||||
|
||||
/// <summary>
|
||||
/// Scheduler Execution Stopped
|
||||
/// </summary>
|
||||
internal static void State_SchedulerExecution_Stopped() { App.State.SetStateValue<bool>(App.StateKey.Scheduler_Started_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Is the Scheduler Executing?
|
||||
/// </summary>
|
||||
/// <returns>true if yes, false if no</returns>
|
||||
internal static bool State_IsSchedulerBackupExecuting() { return App.State.GetStateValue<bool>(App.StateKey.SchedulerBackup_Started_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Scheduler Execution Started
|
||||
/// </summary>
|
||||
internal static void State_SchedulerBackupExecution_Started() { App.State.SetStateValue<bool>(App.StateKey.SchedulerBackup_Started_bool, true); }
|
||||
|
||||
/// <summary>
|
||||
/// Scheduler Execution Stopped
|
||||
/// </summary>
|
||||
internal static void State_SchedulerBackupExecution_Stopped() { App.State.SetStateValue<bool>(App.StateKey.SchedulerBackup_Started_bool, false); }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application State - CommandLine State
|
||||
|
||||
/// <summary>
|
||||
/// Set Application into CommandLine Mode
|
||||
/// </summary>
|
||||
internal static void State_SpecialMode_CommandLineSet() { App.State.SetStateValue<bool>(App.StateKey.SpecialMode_CommandLine_Mode_bool, true); }
|
||||
|
||||
/// <summary>
|
||||
/// Is Application in CommandLine Mode?
|
||||
/// </summary>
|
||||
/// <returns>true if yes, false if no</returns>
|
||||
internal static bool State_SpecialMode_IsCommandLineSet() { return App.State.GetStateValue<bool>(App.StateKey.SpecialMode_CommandLine_Mode_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Set Application into RunAsService Mode
|
||||
/// </summary>
|
||||
internal static void State_SpecialMode_RunAsServiceSet() { App.State.SetStateValue<bool>(App.StateKey.SpecialMode_RunAsService_Mode_bool, true); }
|
||||
|
||||
/// <summary>
|
||||
/// Is Application in RunAsService Mode?
|
||||
/// </summary>
|
||||
/// <returns>true if yes, false if no</returns>
|
||||
internal static bool State_SpecialMode_IsRunAsServiceSet() { return App.State.GetStateValue<bool>(App.StateKey.SpecialMode_RunAsService_Mode_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Special Circumstance - Set Console as Attached
|
||||
/// </summary>
|
||||
internal static void State_SpecialCircum_ConsoleWindowIsAttached() { App.State.SetStateValue<bool>(App.StateKey.SpecialCircum_CommandLine_ConsoleWindowIsAttached_bool, true); }
|
||||
|
||||
/// <summary>
|
||||
/// Special Circumstance - Was Console Window Attached?
|
||||
/// </summary>
|
||||
internal static bool State_SpecialCircum_IsConsoleWindowIsAttached() { return App.State.GetStateValue<bool>(App.StateKey.SpecialCircum_CommandLine_ConsoleWindowIsAttached_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Special Circumstance - Set Communication with Main Instance via WCF as Succeeded
|
||||
/// </summary>
|
||||
internal static void State_SpecialCircum_MainMonitorInstance_CommSuccees() { App.State.SetStateValue<bool>(App.StateKey.SpecialCircum_CommandLine_MonitorInstanceExists_bool, true); }
|
||||
|
||||
/// <summary>
|
||||
/// Special Circumstance - Did Communication with Mai Instance via WCF Succeed?
|
||||
/// </summary>
|
||||
/// <returns>true if yes, false if no</returns>
|
||||
internal static bool State_SpecialCircum_DidMainMonitorInstanceCommSucceed() { return App.State.GetStateValue<bool>(App.StateKey.SpecialCircum_CommandLine_MonitorInstanceExists_bool, false); }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Applicaton State - Special States
|
||||
|
||||
/// <summary>
|
||||
/// Special Circumstance - Set that the Application won't close Applications on Exit * Useful for Auto-Updating the Software *
|
||||
/// </summary>
|
||||
internal static void State_SpecialCircum_DontCloseApplicationsOnExit() { App.State.SetStateValue<bool>(App.StateKey.SpecialCircum_DontCloseApplicationsOnExit_bool, true); }
|
||||
|
||||
/// <summary>
|
||||
/// Special Circumstance - Check to see if we should Close Applications when Exiting
|
||||
/// </summary>
|
||||
/// <returns>true if yes, don't close, false if no</returns>
|
||||
internal static bool State_SpecialCircum_ShouldWeNotCloseApplicationsOnExit() { return App.State.GetStateValue<bool>(App.StateKey.SpecialCircum_DontCloseApplicationsOnExit_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if html is available
|
||||
/// </summary>
|
||||
/// <returns>true, if available, false otherwise</returns>
|
||||
internal static bool State_HtmlHelpIsAvailable() { return App.State.GetStateValue<bool>(App.StateKey.Help_Is_Available_bool, false); }
|
||||
|
||||
/// <summary>
|
||||
/// Set Html Help File as available
|
||||
/// </summary>
|
||||
internal static void State_HtmlHelpAvailable() { App.State.SetStateValue<bool>(App.StateKey.Help_Is_Available_bool, true); }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unhandled Expections! IMP - Show WinForm and Log
|
||||
|
||||
/// <summary>
|
||||
/// * Generic Unhandled Exception Handler *
|
||||
/// Handles all unhandled Exceptions for the Entire AppDomain.
|
||||
/// First Show a Window Message Box, so that we can for sure capture the message
|
||||
/// Second Log it
|
||||
/// </summary>
|
||||
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Exception ex = (Exception)e.ExceptionObject;
|
||||
|
||||
// Exeption to capture error information
|
||||
string exceptionMessage = AppResx.GetString("FATAL_ERROR_HEADER");
|
||||
exceptionMessage = AppResx.GetStringFormated("FATAL_ERROR_APPLICATION_WILL_EXIT", APPLICATION_NAME_LONG);
|
||||
exceptionMessage += ex.Message + "\n\n";
|
||||
if (!String.IsNullOrEmpty(ex.StackTrace))
|
||||
exceptionMessage += ex.StackTrace.Substring(0, 880) + "\n\n";
|
||||
if(!String.IsNullOrEmpty(ex.InnerException.Message))
|
||||
exceptionMessage += ex.InnerException.Message + "\n\n";
|
||||
if (!String.IsNullOrEmpty(ex.Source))
|
||||
exceptionMessage += ex.Source + "\n\n";
|
||||
|
||||
// Polite Message to Show in Message Box
|
||||
string PoliteExceptionMessage = exceptionMessage +
|
||||
AppResx.GetStringFormated("CONTACT_SUPPORT_URGENTLY", SUPPORT_PHONENUMBER) +
|
||||
AppResx.GetStringFormated("ERROR_LOG_FILE_LOCATION", APP_LOG_FILENAME, APP_LOG_PATH);
|
||||
|
||||
// Show Message Box First - Guaranteed to work (Polite Exception Message)
|
||||
MessageBox.Show(PoliteExceptionMessage, AppResx.GetStringFormated("APPLICATION_FATAL_ERROR", APPLICATION_NAME_SHORT), MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
|
||||
// Log the Error to the Main Log File
|
||||
CreateAppMainLogging().Fatal(exceptionMessage, ex);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fatal Exception! IMP - Show WinForm, Log, and Exit the Application
|
||||
|
||||
/// <summary>
|
||||
/// Some Events continue execution, even though a fatal exception occured (.net!)
|
||||
/// This flag allows those functions to check for this and stop processing
|
||||
/// </summary>
|
||||
public static bool s_FatalErrorOccured = false;
|
||||
|
||||
/// <summary>
|
||||
/// Custom User Specified Fatal Exception Occured * Stops Application Execution *
|
||||
/// </summary>
|
||||
/// <param name="Message">Message to show/log</param>
|
||||
//public static void FatalExceptionStopExecution(string Message, bool bShowMessageBox = true)
|
||||
public static void FatalExceptionStopExecution(string Message, bool bShowMessageBox)
|
||||
{
|
||||
s_FatalErrorOccured = true;
|
||||
log.Fatal(Message);
|
||||
if(bShowMessageBox && !App.State_SpecialMode_IsRunAsServiceSet())
|
||||
MsgBox.ShowFatalError(Message, "", Forms.MessageBoxButtons.OK);
|
||||
App.Current.Shutdown();
|
||||
|
||||
// To make 100% sure, that we are exiting... (not needed)
|
||||
//System.Diagnostics.Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application Multi-File Assembly Handling
|
||||
|
||||
/// <summary>
|
||||
/// A way to embed multiple dlls into one exe:
|
||||
/// http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx
|
||||
/// </summary>
|
||||
/// <returns>a loaded assembly if found, null otherwise</returns>
|
||||
System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
string curAssemblyName = AssemblyW.GetAssemblyName(AssemblyW.AssemblyST.Executing);
|
||||
String resourceName = curAssemblyName + ".Components." + new AssemblyName(args.Name).Name + ".dll";
|
||||
|
||||
//string[] resources = AssemblyW.SpecializedAssemblyInfo.GetAssemblyResourceNames(AssemblyW.AssemblyST.Entry);
|
||||
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
|
||||
if(stream != null)
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
Byte[] assemblyData = new Byte[stream.Length];
|
||||
stream.Read(assemblyData, 0, assemblyData.Length);
|
||||
return Assembly.Load(assemblyData);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application Startup N' Exit
|
||||
|
||||
/// <summary>
|
||||
/// Handles the Application StartUp event
|
||||
/// </summary>
|
||||
private void Application_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
// We need to make sure that the Permissions are set correctly for
|
||||
// the ProgramData/AllUser folder for ALL our configuration files
|
||||
Installer.GrantFullPermissionToFolderForUserOrGroup(APP_XML_DS_PATH, "Everyone");
|
||||
|
||||
// Create the First Main Log Instance
|
||||
log = CreateAppMainLogging();
|
||||
|
||||
// Parse the Command Line
|
||||
cmdline.Parse(e.Args);
|
||||
|
||||
// Delay Start * Imp. for Auto-Update Feature
|
||||
string[] activationData = null;
|
||||
if(AppDomain.CurrentDomain.SetupInformation.ActivationArguments != null)
|
||||
activationData = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData;
|
||||
if (activationData != null && activationData.Length > 0)
|
||||
{
|
||||
uint uDelayStart = 0;
|
||||
if (uint.TryParse(activationData[0], out uDelayStart) && (uDelayStart > 0))
|
||||
{
|
||||
App.log.Info(String.Format("Auto Update Delay Start Called with {0} Seconds", uDelayStart));
|
||||
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(uDelayStart));
|
||||
}
|
||||
}
|
||||
|
||||
// If Command-Line has params, we are being launched in Command-Line Mode * Hence, we put
|
||||
// the app into a different State *
|
||||
if (cmdline.HasParams && !cmdline.GetFlagValue(CommandLine_Flag.RUNASSERVICE)) // RunAsService is NOT Command-line Mode
|
||||
{
|
||||
App.State_SpecialMode_CommandLineSet();
|
||||
log.Info(AppResx.GetStringFormated("APPLICATION_STARTED_COMMANDLINE_MODE", APPLICATION_NAME_SHORT, cmdline.ParsedArgs(), APPLICATION_VERSION));
|
||||
}
|
||||
else if (cmdline.HasParams && cmdline.GetFlagValue(CommandLine_Flag.RUNASSERVICE)) // RunAsService is it's own Mode
|
||||
{
|
||||
State_SpecialMode_RunAsServiceSet();
|
||||
log.Info(AppResx.GetStringFormated("APPLICATION_STARTED_SERVICE_MODE", APPLICATION_NAME_SHORT, cmdline.ParsedArgs(), APPLICATION_VERSION));
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Info(AppResx.GetStringFormated("APPLICATION_STARTED", APPLICATION_NAME_SHORT, APPLICATION_VERSION));
|
||||
}
|
||||
|
||||
// Configure our Message Boxes
|
||||
ConfigureAppMainMsgBox();
|
||||
|
||||
// Create the Xml File Instance * To Read/Write DataStore *
|
||||
// ~Also, don't allow the configuration to add this Application to the Configuration
|
||||
DelegateCollection.Void_Param1_Exception_Func XmlFileExceptionHandler = delegate(Exception ex)
|
||||
{
|
||||
App.log.Error("Saving MonitorDataStore XMLFile Error Thrown", ex);
|
||||
if(!App.State_SpecialMode_IsRunAsServiceSet())
|
||||
MsgBox.ShowError("Saving XMLDataStore XMLFile Error " + ex.Message, "", Forms.MessageBoxButtons.OK);
|
||||
};
|
||||
List<string> excludedProcessNames = new List<String>();
|
||||
excludedProcessNames.Add(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileName(AssemblyW.AssemblyST.Entry));
|
||||
xmlfile = new MonitorDataStore(App.APP_XML_DS_FILENAMEANDPATH, excludedProcessNames, XmlFileExceptionHandler);
|
||||
|
||||
// If this is a Debug build, enable * Performance Tracing *
|
||||
#if DEBUG
|
||||
TraceM.EnableTracing = true;
|
||||
#endif
|
||||
|
||||
// Make sure that the File Name of this Assembly matches the Assembly Name,
|
||||
// this allows us to enforce for sure that only One Instance of this program is running
|
||||
// i.e. someone could run this program otherwise by just changing the filename
|
||||
string entryAssemblyName = AssemblyW.GetAssemblyName(AssemblyW.AssemblyST.Entry);
|
||||
string entryAssemblyFileName = AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileName(AssemblyW.AssemblyST.Entry);
|
||||
if (String.Compare(entryAssemblyName, entryAssemblyFileName, true) != 0)
|
||||
FatalExceptionStopExecution(AppResx.GetStringFormated("FATAL_ERROR_ASSEMBLY_FILENAME_MISMATCH", entryAssemblyName, entryAssemblyFileName), true);
|
||||
|
||||
// Check that this is the ONLY Instance running on this Machine
|
||||
// ~We only allow one instance of this app to be running... (Only Do this if NOT in Command-Line Mode)
|
||||
if (!s_FatalErrorOccured && !App.State_SpecialMode_IsCommandLineSet())
|
||||
{
|
||||
// Check if there are other instances. Start/Stop/Etc won't work if other instances are not running
|
||||
bool bAnotherInstanceIsRunning = true;
|
||||
#if DEBUG
|
||||
bAnotherInstanceIsRunning = !ProcessW.IsTheOnlyProcessRunning(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileName(AssemblyW.AssemblyST.Entry).ToLower(), false);
|
||||
#else
|
||||
bAnotherInstanceIsRunning = !ProcessW.IsTheOnlyProcessRunning(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileName(AssemblyW.AssemblyST.Entry).ToLower(), true);
|
||||
#endif
|
||||
if (bAnotherInstanceIsRunning)
|
||||
{
|
||||
// Alert the User and ask the User, if they would like to close that process,
|
||||
// * Could be that The Application Errored out, yet still remains running, so they are trying to restart it *
|
||||
Process[] ps = null;
|
||||
#if DEBUG
|
||||
ps = ProcessW.AllRunningProcessesOf(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileName(AssemblyW.AssemblyST.Entry).ToLower(), false, true);
|
||||
#else
|
||||
ps = ProcessW.AllRunningProcessesOf(AssemblyW.SpecializedAssemblyInfo.GetAssemblyFileName(AssemblyW.AssemblyST.Entry).ToLower(), true, true);
|
||||
#endif
|
||||
Forms.DialogResult dr = System.Windows.Forms.DialogResult.Ignore;
|
||||
if (!App.State_SpecialMode_IsRunAsServiceSet())
|
||||
{
|
||||
string msg = AppResx.GetStringFormated("FATAL_ERROR_OTHER_INSTANCES", App.APPLICATION_NAME_SHORT);
|
||||
msg += "\nWould you like to try to force close the other instance(s)?\n";
|
||||
msg += "\nClicking 'Yes' will force all other instances to close.";
|
||||
msg += "\nClicking 'No' will close this instance.";
|
||||
dr = MsgBox.ShowInfo(msg, "Other Instance Found", Forms.MessageBoxButtons.YesNo);
|
||||
}
|
||||
|
||||
// Check Dialog Result (If in GUI MODE)
|
||||
if (dr == Forms.DialogResult.Yes)
|
||||
{
|
||||
// try to kill all other instances
|
||||
bool bSuccess = true;
|
||||
foreach (Process p in ps)
|
||||
{
|
||||
if(Process.GetCurrentProcess().Id != p.Id)
|
||||
bSuccess = PStarter.KillProcess((uint)p.Id, false, 1, true, 2);
|
||||
if (!bSuccess)
|
||||
break;
|
||||
}
|
||||
if (!bSuccess)
|
||||
{
|
||||
App.log.Error("Error occured closing other instances");
|
||||
FatalExceptionStopExecution(AppResx.GetStringFormated("FATAL_ERROR_OTHER_INSTANCES", App.APPLICATION_NAME_SHORT), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// * Opportunity To Start the WCF Host *
|
||||
WCFHost.StartHost();
|
||||
|
||||
// Refresh the taskbar, after killing any instances
|
||||
Watchdog.WatchdogLib.Win32.Functions.RefreshTaskbarNotificationArea();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalExceptionStopExecution(AppResx.GetStringFormated("FATAL_ERROR_OTHER_INSTANCES", App.APPLICATION_NAME_SHORT), false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// * Opportunity To Start the WCF Host *
|
||||
WCFHost.StartHost();
|
||||
|
||||
// * Opportunity to load the chm help file *
|
||||
// ~Force a new chm file write, if an upgrade occured
|
||||
try
|
||||
{
|
||||
#if DEBUG
|
||||
bool bForceCreationOfNewCHMFile = true;
|
||||
#else
|
||||
bool bForceCreationOfNewCHMFile = (App.APPLICATION_VERSION != App.setting.LastProgramVersion);
|
||||
#endif
|
||||
string curAssemblyName = AssemblyW.GetAssemblyName(AssemblyW.AssemblyST.Executing);
|
||||
App.chmhelp = new CHMFile(Assembly.GetExecutingAssembly().GetManifestResourceStream(curAssemblyName + "." + "Watchdog.chm"), App.APPLICATION_NAME_SHORT, bForceCreationOfNewCHMFile);
|
||||
if (App.chmhelp != null)
|
||||
App.State_HtmlHelpAvailable(); // Html Help loaded successfully
|
||||
if (bForceCreationOfNewCHMFile && (App.chmhelp != null))
|
||||
App.setting.LastProgramVersion = App.APPLICATION_VERSION;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.log.Error("Failed to create chm Helf File", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!s_FatalErrorOccured && App.State_SpecialMode_IsCommandLineSet())
|
||||
{
|
||||
// We are called with CmdLine Parameters * Try Attaching to the console, in case we got called from a Command Window *
|
||||
bool bAttachSuccess = Watchdog.WatchdogLib.Win32.Kernel32.AttachConsole(-1);
|
||||
App.log.Info(String.Format("CommandLineMode - Attached to Console is {0}", bAttachSuccess));
|
||||
if (bAttachSuccess)
|
||||
App.State_SpecialCircum_ConsoleWindowIsAttached();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the Application Exit event.
|
||||
/// </summary>
|
||||
private void Application_Exit(object sender, ExitEventArgs e)
|
||||
{
|
||||
if (!App.State_SpecialMode_IsCommandLineSet())
|
||||
{
|
||||
log.Info(AppResx.GetStringFormated("APPLICATION_ENDED", APPLICATION_NAME_SHORT, APPLICATION_VERSION));
|
||||
|
||||
// * Opportunity To Stop the WCF Host *
|
||||
WCFHost.StopHost();
|
||||
}
|
||||
else if(App.State_SpecialMode_IsCommandLineSet())
|
||||
{
|
||||
if(App.State_SpecialCircum_IsConsoleWindowIsAttached())
|
||||
{
|
||||
bool bFreeSuccess = Watchdog.WatchdogLib.Win32.Kernel32.FreeConsole();
|
||||
App.log.Info(String.Format("CommandLineMode - Free from Console is {0}", bFreeSuccess));
|
||||
}
|
||||
log.Info(AppResx.GetStringFormated("APPLICATION_ENDED_COMMANDLINE_MODE", APPLICATION_NAME_SHORT, APPLICATION_VERSION));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
161
@integrate/AppState.cs
Normal file
161
@integrate/AppState.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Watchdog.WatchdogLib.Other;
|
||||
|
||||
namespace Watchdog
|
||||
{
|
||||
/// <summary>
|
||||
/// Keeps Track of RunTime State Variables/Objects
|
||||
/// </summary>
|
||||
public static class AppState
|
||||
{
|
||||
private static object s_LockObject = new Object();
|
||||
|
||||
#region Internal State Check Functions
|
||||
|
||||
/// <returns>true if the Process Monitor is running, false otherwise</returns>
|
||||
internal static bool IsMonitorRunning()
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.GetStateValue<bool>(AppState.StateKey.ProcessMonitorStarted_bool, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>true if the Scheduler is running, false otherwise</returns>
|
||||
internal static bool IsSchedulerRunning()
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.GetStateValue<bool>(AppState.StateKey.SchedulerIsRunning_bool, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>true if the Process Monitor encountered errors, false otherwise</returns>
|
||||
internal static bool DidMonitorEncounterErrors()
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.GetStateValue<bool>(AppState.StateKey.ProcessMonitorEncounteredErrors_bool, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>true if the Application is called with Command-Line Parameters, false otherwise</returns>
|
||||
internal static bool IsInCommandLinePrmsMode()
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.GetStateValue<bool>(AppState.StateKey.IsInCommandLineMode_bool, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>true if the Application is attached to a Console Window For Output, false otherwise</returns>
|
||||
internal static bool IsAttachedToConsoleWindow()
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.GetStateValue<bool>(AppState.StateKey.IsAttachedToConsoleWindow_bool, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>When the application is in commandline mode, we want to make sure that a 'real' monitor instance is running,
|
||||
/// in order to communicate with it, this keeps track if that other instance is available</returns>
|
||||
internal static bool InCommandLineMode_IsMonitorInstanceAvailable()
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.GetStateValue<bool>(AppState.StateKey.InCommandLineMode_IsMonitorInstanceAvailable_bool, false);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal State Set Functions
|
||||
|
||||
/// <summary>
|
||||
/// Use this to set the Monitor is Running state to true/false
|
||||
/// </summary>
|
||||
internal static bool MonitorIsRunning(bool bIsRunning)
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.SetStateValue<bool>(AppState.StateKey.ProcessMonitorStarted_bool, bIsRunning);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to set the Scheduler is Running state to true/false
|
||||
/// </summary>
|
||||
internal static bool SchedulerIsRunning(bool bIsRunning)
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.SetStateValue<bool>(AppState.StateKey.SchedulerIsRunning_bool, bIsRunning);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to set the Monitor's Error State
|
||||
/// </summary>
|
||||
internal static bool MonitorEncounterErrors(bool bErrorsOccured)
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.SetStateValue<bool>(AppState.StateKey.ProcessMonitorEncounteredErrors_bool, bErrorsOccured);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to set that the Application is called with Command-Line Parameters
|
||||
/// </summary>
|
||||
internal static bool CommandLinePrmsMode(bool bIsInCommandLinePrmsMode)
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.SetStateValue<bool>(AppState.StateKey.IsInCommandLineMode_bool, bIsInCommandLinePrmsMode);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to set that the Application is attached to a Console Window for Output
|
||||
/// </summary>
|
||||
internal static bool AttachedToConsoleWindow(bool bItIsAttached)
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.SetStateValue<bool>(AppState.StateKey.IsAttachedToConsoleWindow_bool, bItIsAttached);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to set that the Application can communicate with the 'real' monitor instance that is running.
|
||||
/// </summary>
|
||||
internal static bool CommandLineMode_IsMonitorInstanceAvailable(bool bIsAvailable)
|
||||
{
|
||||
lock (s_LockObject)
|
||||
{
|
||||
return AppState.State.GetStateValue<bool>(AppState.StateKey.InCommandLineMode_IsMonitorInstanceAvailable_bool, bIsAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Various Keys that we can use to save/get the GUI State
|
||||
/// </summary>
|
||||
internal enum StateKey
|
||||
{
|
||||
ProcessMonitorStarted_bool,
|
||||
ProcessMonitorEncounteredErrors_bool,
|
||||
SchedulerIsRunning_bool,
|
||||
IsInCommandLineMode_bool,
|
||||
IsAttachedToConsoleWindow_bool,
|
||||
InCommandLineMode_IsMonitorInstanceAvailable_bool,
|
||||
}
|
||||
|
||||
// Initialize BkgdState
|
||||
internal static readonly StateM State = new StateM(typeof(StateKey));
|
||||
}
|
||||
}
|
||||
311
@integrate/CMDlineHandler.cs
Normal file
311
@integrate/CMDlineHandler.cs
Normal file
@@ -0,0 +1,311 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using WatchdogLib;
|
||||
using Watchdog.WatchdogLib.WinForms;
|
||||
using Watchdog.WatchdogLib.Win32;
|
||||
|
||||
namespace Watchdog
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles CommandLine Logic
|
||||
/// </summary>
|
||||
public static class CMDlineHandler
|
||||
{
|
||||
// Our WCF Client object stub
|
||||
private static IWatchdog _proxyObj = null;
|
||||
|
||||
/// <summary>
|
||||
/// Shows the Command Line Help either as a Windows Form or
|
||||
/// to the Console * Depending if a Console Window is Attached *
|
||||
/// </summary>
|
||||
private static void ShowCommandLineHelp()
|
||||
{
|
||||
bool bToConsole = App.State_SpecialCircum_IsConsoleWindowIsAttached();
|
||||
string cmdHelpText = "";
|
||||
|
||||
cmdHelpText += "\n";
|
||||
cmdHelpText += "**************************************************************\n";
|
||||
cmdHelpText += " Make changes to the .xml Configuration.\n";
|
||||
cmdHelpText += "**************************************************************\n";
|
||||
cmdHelpText += "-Add_Process \"Application Exe;Prms;WorkingDir\"\n";
|
||||
cmdHelpText += "-Remove_Process \"Application Exe;Prms\"\n";
|
||||
cmdHelpText += "-Add_Service \"Service Name\"\n";
|
||||
cmdHelpText += "-Remove_Service \"Service Name\"\n";
|
||||
cmdHelpText += "**************************************************************\n";
|
||||
cmdHelpText += " View the .xml Configuration.\n";
|
||||
cmdHelpText += "**************************************************************\n";
|
||||
cmdHelpText += "-Show_Processes\n";
|
||||
cmdHelpText += "-Show_Services\n";
|
||||
cmdHelpText += "**************************************************************\n";
|
||||
cmdHelpText += " Manipulate a Running Monitor Instance.\n";
|
||||
cmdHelpText += "**************************************************************\n";
|
||||
cmdHelpText += "-Start\n";
|
||||
cmdHelpText += "-Pause\n";
|
||||
cmdHelpText += "-Restart\n";
|
||||
cmdHelpText += "-Restart_All\n";
|
||||
cmdHelpText += "-Stop\n";
|
||||
cmdHelpText += "-Stop_All\n";
|
||||
cmdHelpText += "**************************************************************\n";
|
||||
cmdHelpText += "-? Show Help.\n\n";
|
||||
|
||||
// Show Help to the User (Either to the console or a Message Window)
|
||||
if (bToConsole)
|
||||
Console.Write(cmdHelpText);
|
||||
else
|
||||
MsgBox.ShowInfo(cmdHelpText, (App.APPLICATION_NAME_SHORT + " Command Line Help"), System.Windows.Forms.MessageBoxButtons.OK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Either writes out to the console or shows a message box, if we want to alert the user
|
||||
/// </summary>
|
||||
/// <param name="str">string to write out</param>
|
||||
private static void WriteOut(string str)
|
||||
{
|
||||
bool bToConsole = App.State_SpecialCircum_IsConsoleWindowIsAttached();
|
||||
if (bToConsole)
|
||||
Console.WriteLine("\n" + str);
|
||||
else
|
||||
MsgBox.ShowInfo(str, (App.APPLICATION_NAME_SHORT + " Command Line Alert"), System.Windows.Forms.MessageBoxButtons.OK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main Entry Point for CommandLine Mode * When Application is being called with
|
||||
/// CommandLine Parameters *
|
||||
/// </summary>
|
||||
static public void EnterCommandLineMode()
|
||||
{
|
||||
// Show Help?
|
||||
if (App.cmdline.ShowHelp || !App.cmdline.ParamsValid)
|
||||
{
|
||||
ShowCommandLineHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check now using WCF...
|
||||
// Now we need to check communication with the other instance,
|
||||
// if there isn't another process, then start/stop/restart/etc,.. won't work
|
||||
_proxyObj = WCFHost.GetWatchDogClientInterface();
|
||||
if (_proxyObj != null)
|
||||
App.State_SpecialCircum_MainMonitorInstance_CommSuccees();
|
||||
else
|
||||
App.log.Info("No other Instances found, Command-line parameter functionallity limited to making configuration changes only");
|
||||
|
||||
// Now let's go thru all the CommandLine_Flags * WCF *
|
||||
DealWithApplicationStateWCFCalls_CommandLineFlags();
|
||||
|
||||
// Now let's go thru all the CommandLine_Flags * Non-WCF *
|
||||
DealWithDisplayConfigurationNonWCFCalls_CommandLineFlags();
|
||||
|
||||
// Now let's go thru all the CommandLine_Options * Non-WCF *
|
||||
DealWithConfigurationChanges_CommandLineOptions();
|
||||
|
||||
// Done Here
|
||||
_proxyObj = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deals with all the State Changes for the Main Application
|
||||
/// * Via WCF * calls into main app and makes those changes
|
||||
/// </summary>
|
||||
private static void DealWithApplicationStateWCFCalls_CommandLineFlags()
|
||||
{
|
||||
// Now let's go thru all the CommandLine_Flags * WCF *
|
||||
if (App.State_SpecialCircum_DidMainMonitorInstanceCommSucceed())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (App.cmdline.GetFlagValue(App.CommandLine_Flag.START))
|
||||
{
|
||||
_proxyObj.StartMonitoring();
|
||||
}
|
||||
else if (App.cmdline.GetFlagValue(App.CommandLine_Flag.STOP))
|
||||
{
|
||||
_proxyObj.StopMonitoring();
|
||||
}
|
||||
else if (App.cmdline.GetFlagValue(App.CommandLine_Flag.STOP_ALL))
|
||||
{
|
||||
_proxyObj.StopAllMonitoring();
|
||||
}
|
||||
else if (App.cmdline.GetFlagValue(App.CommandLine_Flag.RESTART))
|
||||
{
|
||||
_proxyObj.RestartMonitoring();
|
||||
}
|
||||
else if (App.cmdline.GetFlagValue(App.CommandLine_Flag.RESTART_ALL))
|
||||
{
|
||||
_proxyObj.RestartAllMonitoring();
|
||||
}
|
||||
else if (App.cmdline.GetFlagValue(App.CommandLine_Flag.PAUSE))
|
||||
{
|
||||
_proxyObj.PauseMonitoring();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.log.Error("Error Occured processing CommandLine_Flag via WCF", ex);
|
||||
|
||||
// Alert the user
|
||||
WriteOut(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deals with all the Flags that deal with displaying configuration. does this locally * in this process *
|
||||
/// View Configuration. Also handles LockWorkstation (Feature).
|
||||
/// </summary>
|
||||
private static void DealWithDisplayConfigurationNonWCFCalls_CommandLineFlags()
|
||||
{
|
||||
if (App.cmdline.GetFlagValue(App.CommandLine_Flag.LOCK))
|
||||
{
|
||||
// Hidden Feature, allows us to specify in windows start-up to lock the workstation
|
||||
if (!User32.LockWorkStation())
|
||||
{
|
||||
App.log.Error("LockWorkstation() Failed");
|
||||
WriteOut("LockWorkstation Failed");
|
||||
}
|
||||
}
|
||||
else if (App.cmdline.GetFlagValue(App.CommandLine_Flag.SHOW_PROCESSES))
|
||||
{
|
||||
// write out each process
|
||||
string[] processes = WCFHost.ShowProcesses();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (processes != null && processes.Length != 0)
|
||||
{
|
||||
foreach (string p in processes)
|
||||
{
|
||||
sb.Append(p);
|
||||
sb.Append("\n");
|
||||
}
|
||||
}
|
||||
if (sb.Length > 0)
|
||||
WriteOut(sb.ToString());
|
||||
}
|
||||
else if (App.cmdline.GetFlagValue(App.CommandLine_Flag.SHOW_SERVICES))
|
||||
{
|
||||
// write out each service
|
||||
string[] services = WCFHost.ShowServices();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (services != null && services.Length != 0)
|
||||
{
|
||||
foreach (string s in services)
|
||||
{
|
||||
sb.Append(s);
|
||||
sb.Append("\n");
|
||||
}
|
||||
}
|
||||
if (sb.Length > 0)
|
||||
WriteOut(sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deals with making configuration changes. does this locally * in this process *
|
||||
/// Add/Remove Configuration
|
||||
/// </summary>
|
||||
private static void DealWithConfigurationChanges_CommandLineOptions()
|
||||
{
|
||||
string ProcessAdd = App.cmdline.GetOptionValue<string>(App.CommandLine_Option.ADD_PROCESS, String.Empty);
|
||||
if (String.IsNullOrEmpty(ProcessAdd))
|
||||
{
|
||||
string ProcessRemove = App.cmdline.GetOptionValue<string>(App.CommandLine_Option.REMOVE_PROCESS, String.Empty);
|
||||
if (String.IsNullOrEmpty(ProcessRemove))
|
||||
{
|
||||
string ServiceAdd = App.cmdline.GetOptionValue<string>(App.CommandLine_Option.ADD_SERVICE, String.Empty);
|
||||
if (String.IsNullOrEmpty(ServiceAdd))
|
||||
{
|
||||
string ServiceRemove = App.cmdline.GetOptionValue<string>(App.CommandLine_Option.REMOVE_SERVICE, String.Empty);
|
||||
if (!String.IsNullOrEmpty(ServiceRemove))
|
||||
{
|
||||
bool bRemoved = WCFHost.RemoveService(ServiceRemove);
|
||||
if (bRemoved)
|
||||
{
|
||||
WriteOut(String.Format("Service '{0}' removed successfully from Configuration", ServiceRemove));
|
||||
App.log.Info(String.Format("Service '{0}' removed successfully from Configuration", ServiceRemove));
|
||||
|
||||
// * Reload on Main Instance, if possible *
|
||||
if (App.State_SpecialCircum_DidMainMonitorInstanceCommSucceed()) _proxyObj.ReloadConfigurationNextInterval();
|
||||
App.xmlfile.ForceRefreshOnNext_ReadData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteOut(String.Format("Service '{0}' failed to be removed from Configuration", ServiceRemove));
|
||||
App.log.Error(String.Format("Service '{0}' failed to be removed from Configuration", ServiceRemove));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bAdded = WCFHost.AddService(ServiceAdd);
|
||||
if (bAdded)
|
||||
{
|
||||
WriteOut(String.Format("Service '{0}' added successfully to Configuration", ServiceAdd));
|
||||
App.log.Info(String.Format("Service '{0}' added successfully to Configuration", ServiceAdd));
|
||||
|
||||
// * Reload on Main Instance, if possible *
|
||||
if (App.State_SpecialCircum_DidMainMonitorInstanceCommSucceed()) _proxyObj.ReloadConfigurationNextInterval();
|
||||
App.xmlfile.ForceRefreshOnNext_ReadData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteOut(String.Format("Service '{0}' failed to be added to Configuration", ServiceAdd));
|
||||
App.log.Error(String.Format("Service '{0}' failed to be added to Configuration", ServiceAdd));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] pNc = ProcessRemove.Split(';');
|
||||
bool bRemoved = false;
|
||||
if (pNc.Length == 1)
|
||||
bRemoved = WCFHost.RemoveProcess(pNc[0], String.Empty);
|
||||
else if (pNc.Length == 2)
|
||||
bRemoved = WCFHost.RemoveProcess(pNc[0], pNc[1]);
|
||||
if (bRemoved)
|
||||
{
|
||||
WriteOut(String.Format("Application '{0}' with CommandLinePrms '{1}' removed successfully from Configuration", pNc[0], (pNc.Length > 1) ? pNc[1] : ""));
|
||||
App.log.Info(String.Format("Application '{0}' with CommandLinePrms '{1}' removed successfully from Configuration", pNc[0], (pNc.Length > 1) ? pNc[1] : ""));
|
||||
|
||||
// * Reload on Main Instance, if possible *
|
||||
if (App.State_SpecialCircum_DidMainMonitorInstanceCommSucceed()) _proxyObj.ReloadConfigurationNextInterval();
|
||||
App.xmlfile.ForceRefreshOnNext_ReadData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteOut(String.Format("Application '{0}' with CommandLinePrms '{1}' failed to be removed from Configuration", pNc[0], (pNc.Length > 1) ? pNc[1] : ""));
|
||||
App.log.Error(String.Format("Application '{0}' with CommandLinePrms '{1}' failed to be removed from Configuration", pNc[0], (pNc.Length > 1) ? pNc[1] : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] pNc = ProcessAdd.Split(';');
|
||||
bool bAdded = false;
|
||||
if(pNc.Length == 1)
|
||||
bAdded = WCFHost.AddProcess(pNc[0], String.Empty, String.Empty);
|
||||
else if(pNc.Length == 2)
|
||||
bAdded = WCFHost.AddProcess(pNc[0], pNc[1], String.Empty);
|
||||
else if (pNc.Length == 3)
|
||||
bAdded = WCFHost.AddProcess(pNc[0], pNc[1], pNc[2]);
|
||||
if (bAdded)
|
||||
{
|
||||
WriteOut(String.Format("Application '{0}' with CommandLinePrms '{1}' added successfully to Configuration", pNc[0], (pNc.Length > 1) ? pNc[1] : ""));
|
||||
App.log.Info(String.Format("Application '{0}' with CommandLinePrms '{1}' added successfully to Configuration", pNc[0], (pNc.Length > 1) ? pNc[1] : ""));
|
||||
|
||||
// * Reload on Main Instance, if possible *
|
||||
if (App.State_SpecialCircum_DidMainMonitorInstanceCommSucceed()) _proxyObj.ReloadConfigurationNextInterval();
|
||||
App.xmlfile.ForceRefreshOnNext_ReadData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteOut(String.Format("Application '{0}' with CommandLinePrms '{1}' failed to be added to Configuration", pNc[0], (pNc.Length > 1) ? pNc[1] : ""));
|
||||
App.log.Error(String.Format("Application '{0}' with CommandLinePrms '{1}' failed to be added to Configuration", pNc[0], (pNc.Length > 1) ? pNc[1] : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
482
@integrate/CheckActiveTwo.cs
Normal file
482
@integrate/CheckActiveTwo.cs
Normal file
@@ -0,0 +1,482 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PhoneHome
|
||||
{
|
||||
internal class CheckActiveTwo
|
||||
{
|
||||
internal string ProductName = String.Empty;
|
||||
internal string ProductVersion = String.Empty;
|
||||
internal string SerialNumber = String.Empty;
|
||||
private string _LastGeneratedKey = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="ProductName"></param>
|
||||
/// <param name="ProductVersion"></param>
|
||||
/// <param name="SerialNumber"></param>
|
||||
internal CheckActiveTwo(string ProductName, string ProductVersion, string SerialNumber)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(ProductName) && !String.IsNullOrEmpty(ProductVersion) && !String.IsNullOrEmpty(SerialNumber))
|
||||
{
|
||||
this.ProductName = ProductName;
|
||||
this.ProductVersion = ProductVersion;
|
||||
this.SerialNumber = SerialNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("ProductName, ProductVersion, and SerialNumber can't be blank");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="strEncGeneratedString"></param>
|
||||
internal CheckActiveTwo(string strEncGeneratedString)
|
||||
{
|
||||
if (IsValidEncKey(strEncGeneratedString))
|
||||
{
|
||||
_LastGeneratedKey = strEncGeneratedString;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Not a valid Enc String");
|
||||
}
|
||||
}
|
||||
|
||||
#region Static Internal Utilities
|
||||
|
||||
/// <summary>
|
||||
/// Perform checksum on string
|
||||
/// </summary>
|
||||
/// <param name="strAboutToBeChecksummed"></param>
|
||||
/// <returns>Checksum</returns>
|
||||
internal static int PerformChecksum(string strAboutToBeChecksummed)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(strAboutToBeChecksummed))
|
||||
{
|
||||
int nChecksum = 0;
|
||||
for (int i = 0; i < strAboutToBeChecksummed.Length; ++i)
|
||||
{
|
||||
if (Char.IsDigit(strAboutToBeChecksummed[i]))
|
||||
nChecksum = nChecksum + int.Parse(strAboutToBeChecksummed[i].ToString());
|
||||
}
|
||||
return nChecksum;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dash a String
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string MakeIntoDashSeperatedString(string strAboutToBeDashed, int DashEveryNthCharacter)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(strAboutToBeDashed))
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < strAboutToBeDashed.Length; i++)
|
||||
{
|
||||
if ((i != 0) && ((i % DashEveryNthCharacter) == 0))
|
||||
sb.Append("-");
|
||||
sb.Append(strAboutToBeDashed[i]);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Undash a String
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string MakeIntoDashUnseperatedString(string strAboutToBeUndashed)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(strAboutToBeUndashed))
|
||||
return strAboutToBeUndashed.Replace("-", "");
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new Key to use - the key can be used to verify the serial number
|
||||
/// </summary>
|
||||
/// <returns>a new Key</returns>
|
||||
internal string GenerateNewKey()
|
||||
{
|
||||
// GenerateString For User to send
|
||||
string KeyValue = MakeKey();
|
||||
string EncrKey = EncodeShuffle(KeyValue);
|
||||
_LastGeneratedKey = MakeIntoDashSeperatedString(EncrKey, 4);
|
||||
|
||||
// For Debugging
|
||||
string UnEncoded = DecodeShuffle(EncrKey);
|
||||
if (KeyValue != UnEncoded)
|
||||
{
|
||||
// something is terribly wrong with the Encryption
|
||||
Debug.Assert(false);
|
||||
}
|
||||
return _LastGeneratedKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The function should really be called 'GeneratedPIN' but for reverse engineering
|
||||
/// purpose, keeping them guessin * security by obscurity *
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal string GeneraledPiM()
|
||||
{
|
||||
if (!String.IsNullOrEmpty(_LastGeneratedKey))
|
||||
{
|
||||
int KeyChecksum = PerformChecksum(MakeKey());
|
||||
int ShuffledChecksum = PerformChecksum(_LastGeneratedKey);
|
||||
string Result = KeyChecksum.ToString() + ShuffledChecksum.ToString();
|
||||
if (Result.Length < 4)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(Result);
|
||||
int nRemainder = 4 - Result.Length;
|
||||
while (nRemainder > 0) { sb.Append("7"); nRemainder--; }
|
||||
Result = sb.ToString();
|
||||
}
|
||||
Result = Result.Substring(0, 4);
|
||||
int nHour = DateTime.Now.ToUniversalTime().Hour;
|
||||
nHour = (nHour <= 6) ? (nHour + 3) : (nHour - 2);
|
||||
string strHour = String.Format("{0}", (nHour < 10) ? ("8" + nHour.ToString()) : (nHour.ToString()));
|
||||
string fourdigitPin = (strHour[1] + Result[1].ToString() + strHour[0] + Result[3].ToString());
|
||||
int nChecksumPin = PerformChecksum(fourdigitPin);
|
||||
string strChecksumLastDigit = nChecksumPin.ToString()[nChecksumPin.ToString().Length - 1].ToString();
|
||||
return fourdigitPin + strChecksumLastDigit;
|
||||
}
|
||||
else
|
||||
{
|
||||
GenerateNewKey();
|
||||
return GeneraledPiM();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dtStamp"></param>
|
||||
/// <param name="ProductName"></param>
|
||||
/// <param name="ProductVersion"></param>
|
||||
/// <param name="SerialNumber"></param>
|
||||
/// <returns>true, if successful, false otherwise</returns>
|
||||
internal bool RetrieveValues(out DateTime dtStamp, out string ProductName, out string ProductVersion, out string SerialNumber)
|
||||
{
|
||||
dtStamp = DateTime.MinValue;
|
||||
ProductName = String.Empty;
|
||||
ProductVersion = String.Empty;
|
||||
SerialNumber = String.Empty;
|
||||
if (!String.IsNullOrEmpty(_LastGeneratedKey))
|
||||
{
|
||||
string Undashed = MakeIntoDashUnseperatedString(_LastGeneratedKey);
|
||||
if (UnmakeKey(DecodeShuffle(Undashed), out dtStamp, out ProductName, out ProductVersion, out SerialNumber))
|
||||
{
|
||||
this.ProductName = ProductName;
|
||||
this.ProductVersion = ProductVersion;
|
||||
this.SerialNumber = SerialNumber;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Key Generation Functions
|
||||
|
||||
private bool ContainsOnlyDigits(string strToCheckForDigits)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(strToCheckForDigits))
|
||||
{
|
||||
for (int i = 0; i < strToCheckForDigits.Length; ++i)
|
||||
{
|
||||
if (!Char.IsDigit(strToCheckForDigits[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if the Generated string being passed in is a valid generated string
|
||||
/// </summary>
|
||||
/// <param name="strGeneratedString"></param>
|
||||
/// <returns>true if valid, false otherwise</returns>
|
||||
private bool IsValidEncKey(string strEncGeneratedString)
|
||||
{
|
||||
string Undashed = MakeIntoDashUnseperatedString(strEncGeneratedString);
|
||||
DateTime dt;
|
||||
string pName, pVersion, pSerial;
|
||||
if (UnmakeKey(DecodeShuffle(Undashed), out dt, out pName, out pVersion, out pSerial))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a Key to send across (all the info the auth needs)
|
||||
/// </summary>
|
||||
/// <returns>Key with needed Info</returns>
|
||||
private string MakeKey()
|
||||
{
|
||||
//string dtShortTest = DateTime.Now.ToUniversalTime().ToShortDateString().Replace("/", "");
|
||||
DateTime dtUniversal = DateTime.Now.ToUniversalTime();
|
||||
string dtMonth = (dtUniversal.Month > 9) ? String.Format("{0}", dtUniversal.Month) : String.Format("0{0}", dtUniversal.Month);
|
||||
string dtDay = (dtUniversal.Day > 9) ? String.Format("{0}", dtUniversal.Day) : String.Format("0{0}", dtUniversal.Day);
|
||||
string dtYear = dtUniversal.Year.ToString();
|
||||
string dtShort = String.Format("{0}{1}{2}", dtMonth, dtDay, dtYear);
|
||||
string ProductId = ProductName.Substring(0, 1); // should always be 'M' or 'L' // so we use "LMXYZ"
|
||||
string strKey = dtShort + "Z" + ProductId + "Y" + ProductVersion.Split('.')[0] + "X" + SerialNumber;
|
||||
return strKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmake a key * Don't even know why i wrote this, prob. won't end up using this *
|
||||
/// </summary>
|
||||
/// <returns>true if successful, false otheriwise</returns>
|
||||
private bool UnmakeKey(string strAboutToBeUnkeyed, out DateTime dtStamp, out string ProductName, out string ProductVersion, out string SerialNumber)
|
||||
{
|
||||
dtStamp = DateTime.MinValue;
|
||||
ProductName = "";
|
||||
ProductVersion = "";
|
||||
SerialNumber = "";
|
||||
|
||||
//string strKey = dtShort + "Z" + ProductId + "Y" + ProductVersion.Split('.')[0] + "X" + SerialNumber;
|
||||
//0123456Z
|
||||
try
|
||||
{
|
||||
if (!String.IsNullOrEmpty(strAboutToBeUnkeyed))
|
||||
{
|
||||
int nZIndex = strAboutToBeUnkeyed.IndexOf("Z");
|
||||
int nYIndex = strAboutToBeUnkeyed.IndexOf("Y");
|
||||
int nXIndex = strAboutToBeUnkeyed.IndexOf("X");
|
||||
if (nZIndex == -1 || nYIndex == -1 || nXIndex == -1)
|
||||
return false;
|
||||
|
||||
// dtShort
|
||||
string strDT = strAboutToBeUnkeyed.Substring(0, nZIndex);
|
||||
strDT = String.Format("{0}/{1}/{2}", strDT.Substring(0, 2), strDT.Substring(2, 2), strDT.Substring(4));
|
||||
dtStamp = DateTime.Parse(strDT);
|
||||
|
||||
// ProductId
|
||||
string ProductId = strAboutToBeUnkeyed.Substring(nZIndex + 1, 1);
|
||||
if (ProductId == "L")
|
||||
ProductName = "Lytec";
|
||||
else if (ProductId == "M")
|
||||
ProductName = "Medisoft";
|
||||
else
|
||||
return false;
|
||||
|
||||
// ProductVersion
|
||||
string strProductVersion = strAboutToBeUnkeyed.Substring(nYIndex + 1, (nXIndex - nYIndex - 1));
|
||||
if (!String.IsNullOrEmpty(strProductVersion) && ContainsOnlyDigits(strProductVersion))
|
||||
ProductVersion = strProductVersion;
|
||||
else
|
||||
return false;
|
||||
|
||||
// Serial Number
|
||||
SerialNumber = strAboutToBeUnkeyed.Substring(nXIndex + 1);
|
||||
return !String.IsNullOrEmpty(SerialNumber) && ContainsOnlyDigits(SerialNumber);
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// * Simple Encoder *
|
||||
/// </summary>
|
||||
/// <param name="strAboutToBeEncodeShuffled"></param>
|
||||
/// <returns></returns>
|
||||
private string EncodeShuffle(string strAboutToBeEncodeShuffled)
|
||||
{
|
||||
const string Char_CodeLib = "ABCDEFGHIJKNOPQRSTUVW"; //20 - W is never used
|
||||
const string Char_CodeLibExcluded = "LMXYZ"; //5
|
||||
|
||||
if (!String.IsNullOrEmpty(strAboutToBeEncodeShuffled))
|
||||
{
|
||||
List<char> ResultStr = new List<char>(strAboutToBeEncodeShuffled);
|
||||
int nCount = ResultStr.Count;
|
||||
|
||||
// Every N'th Digit do something
|
||||
for (int i = 0; i < nCount; i = i + 3)
|
||||
{
|
||||
char c = ResultStr[i];
|
||||
if (char.IsDigit(c))
|
||||
{
|
||||
int nChar = int.Parse(c.ToString());
|
||||
ResultStr[i] = Char_CodeLib[nChar]; // 0..9
|
||||
}
|
||||
}
|
||||
|
||||
// Every N'th Digit do something
|
||||
for (int i = 0; i < nCount; i = i + 4)
|
||||
{
|
||||
char c = ResultStr[i];
|
||||
if (char.IsDigit(c))
|
||||
{
|
||||
int nChar = int.Parse(c.ToString());
|
||||
ResultStr[i] = Char_CodeLib[nChar + 10]; // 10..19
|
||||
}
|
||||
}
|
||||
|
||||
// Add Randomness to the end of the string
|
||||
Random random = new Random();
|
||||
int nRand = random.Next(1, 9);
|
||||
|
||||
// Perform a Random Shift * So that the code ALWAYS looks different from use to use *
|
||||
for (int i = 0; i < nCount; i = i + 2)
|
||||
{
|
||||
char c = ResultStr[i];
|
||||
if (char.IsLetter(c) && !Char_CodeLibExcluded.Contains(c.ToString()))
|
||||
{
|
||||
int nIndexShifted = Char_CodeLib.IndexOf(c) + nRand;
|
||||
int nIndexShiftedAdj = nIndexShifted % 21;
|
||||
ResultStr[i] = Char_CodeLib[nIndexShiftedAdj]; // 0..20
|
||||
}
|
||||
}
|
||||
|
||||
// Perform another Random Swap * So that the code ALWAYS looks different from use to use *
|
||||
for (int i = 0; i < nCount; i = i + nRand)
|
||||
{
|
||||
char c = ResultStr[i];
|
||||
int nOpposite = nCount - i - 1;
|
||||
char o = ResultStr[nOpposite];
|
||||
if (char.IsLetter(c) && !Char_CodeLibExcluded.Contains(c.ToString()) &&
|
||||
char.IsLetter(o) && !Char_CodeLibExcluded.Contains(o.ToString()))
|
||||
{
|
||||
// swap
|
||||
ResultStr[i] = o;
|
||||
ResultStr[nOpposite] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform a Reversal
|
||||
for (int i = 0; i < (nCount / 2); ++i)
|
||||
{
|
||||
char N1 = ResultStr[i];
|
||||
char N2 = ResultStr[nCount - 1 - i];
|
||||
// swap
|
||||
ResultStr[i] = N2;
|
||||
ResultStr[nCount - 1 - i] = N1;
|
||||
}
|
||||
|
||||
// Add the Randomness to the string for proper decoding to occur
|
||||
ResultStr.Add(Char.Parse(nRand.ToString()));
|
||||
|
||||
// And Return
|
||||
return new String(ResultStr.ToArray());
|
||||
}
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// * Simple Decoder *
|
||||
/// </summary>
|
||||
/// <param name="strAboutToBeDecodeShuffled"></param>
|
||||
/// <returns></returns>
|
||||
private string DecodeShuffle(string strAboutToBeDecodeShuffled)
|
||||
{
|
||||
const string Char_CodeLib = "ABCDEFGHIJKNOPQRSTUVW"; //20
|
||||
const string Char_CodeLibExcluded = "LMXYZ"; //5
|
||||
try
|
||||
{
|
||||
if (!String.IsNullOrEmpty(strAboutToBeDecodeShuffled))
|
||||
{
|
||||
List<char> ResultStr = new List<char>(strAboutToBeDecodeShuffled);
|
||||
|
||||
// retrieve Randomness Factor
|
||||
char cLast = ResultStr[ResultStr.Count - 1];
|
||||
ResultStr.RemoveAt(ResultStr.Count - 1);
|
||||
int nCount = ResultStr.Count;
|
||||
int nRand = int.Parse(cLast.ToString());
|
||||
|
||||
// Perform a Reversal
|
||||
for (int i = 0; i < (nCount / 2); ++i)
|
||||
{
|
||||
char N1 = ResultStr[i];
|
||||
char N2 = ResultStr[nCount - 1 - i];
|
||||
// swap
|
||||
ResultStr[i] = N2;
|
||||
ResultStr[nCount - 1 - i] = N1;
|
||||
}
|
||||
|
||||
// Perform another Random Swap * So that the code ALWAYS looks different from use to use *
|
||||
for (int i = 0; i < nCount; i = i + nRand)
|
||||
{
|
||||
char c = ResultStr[i];
|
||||
int nOpposite = nCount - i - 1;
|
||||
char o = ResultStr[nOpposite];
|
||||
if (char.IsLetter(c) && !Char_CodeLibExcluded.Contains(c.ToString()) &&
|
||||
char.IsLetter(o) && !Char_CodeLibExcluded.Contains(o.ToString()))
|
||||
{
|
||||
// swap
|
||||
ResultStr[i] = o;
|
||||
ResultStr[nOpposite] = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform a Random Shift * So that the code ALWAYS looks different from use to use *
|
||||
for (int i = 0; i < nCount; i = i + 2)
|
||||
{
|
||||
char c = ResultStr[i];
|
||||
if (char.IsLetter(c) && !Char_CodeLibExcluded.Contains(c.ToString()))
|
||||
{
|
||||
int nIndexShifted = Char_CodeLib.IndexOf(c) - nRand;
|
||||
int nIndexShiftedAdj = (nIndexShifted < 0)? 21 + nIndexShifted : nIndexShifted;
|
||||
|
||||
ResultStr[i] = Char_CodeLib[nIndexShiftedAdj]; // 0..20
|
||||
}
|
||||
}
|
||||
|
||||
// Every N'th Digit do something
|
||||
for (int i = 0; i < nCount; i = i + 4)
|
||||
{
|
||||
char c = ResultStr[i];
|
||||
if (char.IsLetter(c) && !Char_CodeLibExcluded.Contains(c.ToString()))
|
||||
{
|
||||
int nIndex = Char_CodeLib.IndexOf(c);
|
||||
if (nIndex >= 10)
|
||||
{
|
||||
nIndex = nIndex - 10;
|
||||
if (nIndex >= 0 && nIndex <= 9)
|
||||
ResultStr[i] = Char.Parse(nIndex.ToString()); // 11..19
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Every N'th Digit do something
|
||||
for (int i = 0; i < nCount; i = i + 3)
|
||||
{
|
||||
char c = ResultStr[i];
|
||||
if (char.IsLetter(c))
|
||||
{
|
||||
int nIndex = Char_CodeLib.IndexOf(c);
|
||||
if (nIndex >= 0 && nIndex <= 9)
|
||||
ResultStr[i] = Char.Parse(nIndex.ToString()); // 1..9
|
||||
}
|
||||
}
|
||||
|
||||
// And Return
|
||||
return new String(ResultStr.ToArray());
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
121
@integrate/ClickOnceUpdater.cs
Normal file
121
@integrate/ClickOnceUpdater.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Deployment.Application;
|
||||
using Forms = System.Windows.Forms;
|
||||
using System.Windows;
|
||||
using System.Diagnostics;
|
||||
using Watchdog.WatchdogLib.WinForms;
|
||||
using System.IO;
|
||||
|
||||
namespace Watchdog
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for Dynamically Checking if there is an update available via ClickOnce
|
||||
/// </summary>
|
||||
public static class ClickOnceUpdater
|
||||
{
|
||||
/// <summary>
|
||||
/// Construction
|
||||
/// </summary>
|
||||
static ClickOnceUpdater(){}
|
||||
|
||||
/// <summary>
|
||||
/// Installs the Update and Restarts the Current Instance
|
||||
/// </summary>
|
||||
/// <returns>false if an error occured, if succesful * Will Restart the App *</returns>
|
||||
internal static bool InstallUpdateAndRestartIfSuccessful()
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateCheckInfo info = null;
|
||||
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
|
||||
if (ad != null)
|
||||
{
|
||||
// Log this to make sure we are sane
|
||||
App.log.Info("Success in retrieving Application Deployment Manifest. This is a ClickOnce App");
|
||||
|
||||
try
|
||||
{
|
||||
info = ad.CheckForDetailedUpdate();
|
||||
}
|
||||
catch (DeploymentDownloadException dde)
|
||||
{
|
||||
MsgBox.ShowInfo("The new version of the application cannot be downloaded at this time. \n\nPlease check your network connection, or try again later. Error: " + dde.Message, "Unable to Download", System.Windows.Forms.MessageBoxButtons.OK);
|
||||
App.log.Info("The new version of the application cannot be downloaded at this time. \n\nPlease check your network connection, or try again later. Error: " + dde.Message);
|
||||
return false;
|
||||
}
|
||||
catch (InvalidDeploymentException ide)
|
||||
{
|
||||
MsgBox.ShowError("Cannot check for a new version of the application. The ClickOnce deployment is corrupt. Please redeploy the application and try again. Error: " + ide.Message, "Invalid Deployment", System.Windows.Forms.MessageBoxButtons.OK);
|
||||
App.log.Error("Cannot check for a new version of the application. The ClickOnce deployment is corrupt. Please redeploy the application and try again. Error: " + ide.Message);
|
||||
return false;
|
||||
}
|
||||
catch (InvalidOperationException ioe)
|
||||
{
|
||||
MsgBox.ShowError("This application cannot be updated. It is likely not a ClickOnce application. Error: " + ioe.Message, "Invalid Operation", System.Windows.Forms.MessageBoxButtons.OK);
|
||||
App.log.Error("This application cannot be updated. It is likely not a ClickOnce application. Error: " + ioe.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info.UpdateAvailable)
|
||||
{
|
||||
Boolean doUpdate = true;
|
||||
|
||||
if (!info.IsUpdateRequired)
|
||||
{
|
||||
Forms.DialogResult dr = MsgBox.ShowInfo("An update is available. Would you like to update\nthe application now?", "Update Available", Forms.MessageBoxButtons.OKCancel);
|
||||
if (!(Forms.DialogResult.OK == dr))
|
||||
doUpdate = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Display a message that the app MUST reboot. Display the minimum required version.
|
||||
MsgBox.ShowInfo("This application has detected a mandatory update from your\ncurrent " +
|
||||
"version to version " + info.MinimumRequiredVersion.ToString() +
|
||||
".\nThe application will now install\nthe update and restart.",
|
||||
"Update Available", System.Windows.Forms.MessageBoxButtons.OK);
|
||||
App.log.Info("This application has detected a mandatory update from your current " +
|
||||
"version to version " + info.MinimumRequiredVersion.ToString() +
|
||||
". The application will now install the update and restart.");
|
||||
}
|
||||
|
||||
if (doUpdate)
|
||||
{
|
||||
try
|
||||
{
|
||||
ad.Update();
|
||||
App.log.Info("The application has been upgraded,and will now restart.");
|
||||
|
||||
// Restart the Application * Imp! Auto-Delay the Start of the new Watchdog Instance *
|
||||
if(File.Exists(App.APPLICATION_CLICKONCE_STARTMENU_LINK))
|
||||
Process.Start(App.APPLICATION_CLICKONCE_STARTMENU_LINK, "15");
|
||||
|
||||
// Auto-Update * No Need to Close Applications *
|
||||
App.State_SpecialCircum_DontCloseApplicationsOnExit();
|
||||
Application.Current.Shutdown();
|
||||
return true;
|
||||
}
|
||||
catch (DeploymentDownloadException dde)
|
||||
{
|
||||
MsgBox.ShowError("Cannot install the latest version of the application. \n\nPlease check your network connection, or try again later. Error: " + dde, "Update Error", System.Windows.Forms.MessageBoxButtons.OK);
|
||||
App.log.Error("Cannot install the latest version of the application. \n\nPlease check your network connection, or try again later. Error: " + dde);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
App.log.Info("Newer Version not available at this time.");
|
||||
MsgBox.ShowInfo("A newer version of the application\nis not available at this time. \n\nPlease try again later.", "Newer Version not available", System.Windows.Forms.MessageBoxButtons.OK);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
276
@integrate/Component.All/Common.cs
Normal file
276
@integrate/Component.All/Common.cs
Normal file
@@ -0,0 +1,276 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BridgeConnector.Lib.Process;
|
||||
using BridgeConnector.Lib.Tools;
|
||||
using System.IO;
|
||||
using BridgeConnector.Lib.File;
|
||||
using BridgeConnector.Lib.XML;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// Common Functions and Helpers Useful for all Installing activities.
|
||||
/// </summary>
|
||||
public static class Common
|
||||
{
|
||||
#region Public Definitions
|
||||
|
||||
public const string INSTALLED_COMPONENT_CONFIG_XML_FILENAME = "InstalledComponentConfig.xml";
|
||||
public const string EMBEDDED_COMPONENT_CONFIG_XML_FILENAME = "EmbeddedComponentConfig.xml";
|
||||
|
||||
/// <summary>
|
||||
/// Allow Setting of Log by external Assembly
|
||||
/// </summary>
|
||||
public static Logging Log
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_Log;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
s_Log = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Statics
|
||||
|
||||
private static ISReadWrite s_isrw = null;
|
||||
private static XSerializer s_serializer = null;
|
||||
private static ComponentConfig s_EmbeddedComponentConfig = null;
|
||||
private static ComponentConfig s_InstalledComponentConfig = null;
|
||||
private static Logging s_Log = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for reading in embedded and installed configuration
|
||||
/// </summary>
|
||||
static Common()
|
||||
{
|
||||
s_isrw = new ISReadWrite(INSTALLED_COMPONENT_CONFIG_XML_FILENAME);
|
||||
s_serializer = new XSerializer();
|
||||
|
||||
//# Read in from Resource (Embedded Components)
|
||||
s_EmbeddedComponentConfig = s_serializer.ReadFromResource<ComponentConfig>(Assembly.GetExecutingAssembly().GetManifestResourceStream("Component.All." + EMBEDDED_COMPONENT_CONFIG_XML_FILENAME));
|
||||
if (s_EmbeddedComponentConfig == null)
|
||||
throw new Exception("Could not read in EmbeddedComponentConfig"); // should never happen
|
||||
|
||||
//# Read in from IS (Currently Installed Components)
|
||||
s_InstalledComponentConfig = s_isrw.ReadFromIS<ComponentConfig>();
|
||||
if (s_InstalledComponentConfig == null)
|
||||
s_InstalledComponentConfig = new ComponentConfig();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Statics
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the EmbeddedComponentConfig
|
||||
/// </summary>
|
||||
/// <returns>the EmbeddedComponentConfig</returns>
|
||||
public static ComponentConfig EmbeddedConfig
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_EmbeddedComponentConfig;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the InstalledComponentConfig
|
||||
/// </summary>
|
||||
/// <returns>the InstalledComponentConfig or null, if not existent</returns>
|
||||
public static ComponentConfig InstalledConfig
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_InstalledComponentConfig;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows Caller to write out any changes to InstalledConfig back to the File
|
||||
/// </summary>
|
||||
public static void WriteOutChangesToInstalledConfig()
|
||||
{
|
||||
s_isrw.WriteToIS<ComponentConfig>(s_InstalledComponentConfig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if any Components are installed. If this returns false, then this is a Fresh Install
|
||||
/// </summary>
|
||||
/// <returns>true, if any components are installed, false otherwise</returns>
|
||||
public static bool AreAnyComponentsInstalled()
|
||||
{
|
||||
bool bIsInstalled = (InstalledConfig != null) && (InstalledConfig.BinaryComponents.Components.Length > 0 || InstalledConfig.SetupComponents.Components.Length > 0);
|
||||
return bIsInstalled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the Index for the Component that matches the specified Unique Label
|
||||
/// </summary>
|
||||
/// <param name="UniqueLabel">label to search components for</param>
|
||||
/// <param name="components">a component array</param>
|
||||
/// <returns>a value >=0 or -1, if not found</returns>
|
||||
public static int GetIndexForComponentUniqueLabel(string UniqueLabel, ComponentConfig.Component[] components)
|
||||
{
|
||||
if (String.IsNullOrEmpty(UniqueLabel) || components == null || components.Length <= 0)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; i < components.Length; ++i)
|
||||
{
|
||||
if (String.Compare(components[i].UniqueLabel, UniqueLabel, true) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawn a Setup Process (Setup.exe for example)
|
||||
/// </summary>
|
||||
public static void PSetupSpwan(string SetupFileNameNPath, string param_s)
|
||||
{
|
||||
PStarter.StartProcess(PStartInfo.CreateProcess(SetupFileNameNPath, param_s, "", true, System.Diagnostics.ProcessWindowStyle.Hidden, false), true, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawn a MSI Setup Process (*.msi)
|
||||
/// </summary>
|
||||
public static void PSetupMSIEXEC(string param_s)
|
||||
{
|
||||
string msiexec = System.Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\msiexec.exe";
|
||||
PStarter.StartProcess(PStartInfo.CreateProcess(msiexec, param_s, "", true, System.Diagnostics.ProcessWindowStyle.Hidden, false), true, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run a command on the commandline * Hidden *
|
||||
/// </summary>
|
||||
/// <param name="cmdline">cmd to run</param>
|
||||
public static string RunCmdLine(string cmdline)
|
||||
{
|
||||
string result = PStarter.RunDosCommand(cmdline);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to get the complete path to a .net framework utility like gacutil.exe or
|
||||
/// installutil.exe.. any .net framework utility. Will fall back to look in the %temp% folder,
|
||||
/// if not found, giving the opportunity to deploy the util directly with the components
|
||||
/// </summary>
|
||||
/// <param name="UtilFileName">the utility in .net you are looking for like gacutil.exe</param>
|
||||
/// <returns>the full filenameNpath or "", if no existing file found</returns>
|
||||
public static string GetNetFrameworkUtilFileNameNPathFile(string UtilFileName)
|
||||
{
|
||||
string windir = System.Environment.GetEnvironmentVariable("windir", EnvironmentVariableTarget.Machine);
|
||||
string NetFramework1_0 = windir + "\\Microsoft.Net\\Framework\\v1.0.3705";
|
||||
string NetFramework1_1 = windir + "\\Microsoft.Net\\Framework\\v1.1.4322";
|
||||
string NetFramework2_0 = windir + "\\Microsoft.Net\\Framework\\v2.0.50727";
|
||||
string NetFramework3_0 = windir + "\\Microsoft.Net\\Framework\\v3.0";
|
||||
string NetFramework3_5 = windir + "\\Microsoft.Net\\Framework\\v3.5";
|
||||
string NetFramework4_0 = windir + "\\Microsoft.Net\\Framework\\v4.0.30319";
|
||||
string TempPath = PathNaming.PathEndsWithNoSlash(Path.GetTempPath()); // We use this as a Fallback, in case file doesn't exist in the framework
|
||||
string[] Frameworks = new string[] { NetFramework2_0, NetFramework4_0, NetFramework1_0, NetFramework1_1, NetFramework3_0, NetFramework3_5, TempPath };
|
||||
|
||||
string NetUtilFileNameNPath = "";
|
||||
foreach (string framework in Frameworks)
|
||||
{
|
||||
if (File.Exists(framework + "\\" + UtilFileName))
|
||||
{
|
||||
NetUtilFileNameNPath = framework + "\\" + UtilFileName;
|
||||
return NetUtilFileNameNPath;
|
||||
}
|
||||
};
|
||||
return NetUtilFileNameNPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quick Helper to get the Program Files Path for the specific system
|
||||
/// </summary>
|
||||
/// <returns>Program Files path with a '/' at the end</returns>
|
||||
public static string GetProgramFilesPathOnSystemWithEndSlash()
|
||||
{
|
||||
string ProgramFiles = System.Environment.GetEnvironmentVariable("ProgramFiles(x86)");
|
||||
if (String.IsNullOrEmpty(ProgramFiles))
|
||||
ProgramFiles = System.Environment.GetEnvironmentVariable("ProgramFiles");
|
||||
return PathNaming.PathEndsWithSlash(ProgramFiles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string SetOwnership()
|
||||
{
|
||||
// in order to do any of this, sadly, we must first install the windows resource kit
|
||||
//subinacl /subdirectories *.* /setowner=domainname\user
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To grant the specified User or group Full Control permissions to the folder and its contents
|
||||
/// </summary>
|
||||
/// <param name="FolderNPath">full path to folder/directory</param>
|
||||
/// <param name="UserOrGroup">domainname\administrator, any windows user or group</param>
|
||||
/// <returns></returns>
|
||||
public static bool GrantFullPermissionToFolderForUserOrGroup(string FolderNPath, string UserOrGroup)
|
||||
{
|
||||
if (Directory.Exists(FolderNPath))
|
||||
{
|
||||
string command = String.Format("cacls \"{0}\" /t /e /g {1}:f", FolderNPath, UserOrGroup);
|
||||
if (command.Contains("Invalid arguments."))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop a service
|
||||
/// </summary>
|
||||
/// <param name="ServiceName">name of service to stop</param>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
public static bool StopService(string ServiceName)
|
||||
{
|
||||
bool bSuccess = true;
|
||||
if (ServiceW.DoesServiceExist(ServiceName))
|
||||
bSuccess = ServiceW.StopService(ServiceName, true, 120);
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// start a service
|
||||
/// </summary>
|
||||
/// <param name="ServiceName">name of a service to start</param>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
public static bool StartService(string ServiceName)
|
||||
{
|
||||
bool bSuccess = true;
|
||||
if (ServiceW.DoesServiceExist(ServiceName))
|
||||
bSuccess = ServiceW.StartService(ServiceName, 120);
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does Service Exist
|
||||
/// </summary>
|
||||
/// <param name="ServiceName">Name of service to check</param>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
public static bool ServiceExists(string ServiceName)
|
||||
{
|
||||
return ServiceW.DoesServiceExist(ServiceName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
62
@integrate/Component.All/Common_MediLytec.cs
Normal file
62
@integrate/Component.All/Common_MediLytec.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// Install Configuration
|
||||
/// </summary>
|
||||
public enum InstallConfig
|
||||
{
|
||||
LytecMD,
|
||||
MedisoftClinical,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Common Functions and Helpers Useful for Lytec, Medisoft Installing activities
|
||||
/// </summary>
|
||||
public static class Common_MediLytec
|
||||
{
|
||||
/// <summary>
|
||||
/// Common/Ofted used #Defs/Definitions associated with Lytec/Medisoft
|
||||
/// </summary>
|
||||
public static class MediLytecPoundDef
|
||||
{
|
||||
public const string BRIDGE_SERVICE_TITLE = "BridgeService";
|
||||
public const string BRIDGE_SERVICE_ASSEMBLY = "BridgeService.exe";
|
||||
public const string BRIDGE_SERVICE_NAME = "McKesson Bridge Service";
|
||||
public const string MIRTH_SERVICE_NAME = "Mirth Connect Service";
|
||||
public const string POSTGRE_SERVICE_NAME = "Mirth_Connect_PostgreSQL_Server";
|
||||
public const string POSTGRE_SERVER_PORT = "5432";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the Configuration (Lytec/Medisoft) from the Registry
|
||||
/// </summary>
|
||||
/// <returns>Lytec/Medisoft</returns>
|
||||
public static InstallConfig RetrieveInstallConfigFromRegistry()
|
||||
{
|
||||
bool bIsLytecInstalled = false;
|
||||
try
|
||||
{
|
||||
RegistryKey reg = Registry.LocalMachine.OpenSubKey("Software\\Lytec", false);
|
||||
bIsLytecInstalled = (reg != null);
|
||||
if (!bIsLytecInstalled) // also check Wow64
|
||||
{
|
||||
reg = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Lytec", false);
|
||||
bIsLytecInstalled = (reg != null);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
|
||||
if (bIsLytecInstalled)
|
||||
return InstallConfig.LytecMD;
|
||||
else
|
||||
return InstallConfig.MedisoftClinical;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
@integrate/Component.All/Component.All.csproj
Normal file
79
@integrate/Component.All/Component.All.csproj
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{94CB1BBA-5CF1-4155-827E-1527032D3921}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Component.All</RootNamespace>
|
||||
<AssemblyName>Component.All</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\Output\Debug\Components\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\..\Output\Release\Components\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Common.cs" />
|
||||
<Compile Include="Common_MediLytec.cs" />
|
||||
<Compile Include="ComponentConfig.cs" />
|
||||
<Compile Include="Component_Binary_Manager.cs" />
|
||||
<Compile Include="Component_Setup_Manager.cs" />
|
||||
<Compile Include="GenericInstaller.cs" />
|
||||
<Compile Include="IInstallComponent.cs" />
|
||||
<Compile Include="IManageComponents.cs" />
|
||||
<Compile Include="ISetup.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BridgeConnectorLib\BridgeConnectorLib.csproj">
|
||||
<Project>{9F60FBD1-0DA0-4558-971F-5BA9EE44493A}</Project>
|
||||
<Name>BridgeConnectorLib</Name>
|
||||
<Private>False</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="EmbeddedComponentConfig.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
223
@integrate/Component.All/ComponentConfig.cs
Normal file
223
@integrate/Component.All/ComponentConfig.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using System.Collections;
|
||||
using BridgeConnector.Lib.Tools;
|
||||
using System.IO;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializable Xml Object used to store all Configuration data
|
||||
/// </summary>
|
||||
[XmlRoot("ComponentConfig", Namespace = "BridgeConnect", IsNullable = false)]
|
||||
public class ComponentConfig
|
||||
{
|
||||
public ComponentW BinaryComponents = null;
|
||||
public ComponentW SetupComponents = null;
|
||||
|
||||
/// <summary>
|
||||
/// XML Embedded Component Configuration
|
||||
/// </summary>
|
||||
public ComponentConfig()
|
||||
{
|
||||
BinaryComponents = new ComponentW();
|
||||
SetupComponents = new ComponentW();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper class for multiple Components
|
||||
/// </summary>
|
||||
public class ComponentW
|
||||
{
|
||||
private ArrayList m_ArrayList;
|
||||
public ComponentW()
|
||||
{
|
||||
m_ArrayList = new ArrayList();
|
||||
}
|
||||
|
||||
[XmlElement("Component")]
|
||||
public Component[] Components
|
||||
{
|
||||
get
|
||||
{
|
||||
Component[] components = new Component[m_ArrayList.Count];
|
||||
m_ArrayList.CopyTo(components);
|
||||
return components;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null) return;
|
||||
Component[] components = (Component[])value;
|
||||
m_ArrayList.Clear();
|
||||
foreach (Component component in components)
|
||||
AddUpdateComponent(component.UniqueLabel, component.Version, component.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
#region Public Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Call this function to Add/Update a component
|
||||
/// </summary>
|
||||
/// <param name="UniqueLabel">unique label used to identify a component</param>
|
||||
/// <param name="Version">Version of the component</param>
|
||||
/// <param name="FileName">FileName of the component</param>
|
||||
public void AddUpdateComponent(string UniqueLabel, string Version, string FileName)
|
||||
{
|
||||
int nIndex = GetIndexForComponent(UniqueLabel);
|
||||
if (nIndex != -1)
|
||||
{
|
||||
Component component = ((Component)m_ArrayList[nIndex]);
|
||||
component.UniqueLabel = UniqueLabel;
|
||||
component.Version = Version;
|
||||
component.FileName = FileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ArrayList.Add(new Component(UniqueLabel, Version, FileName));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this function to remove a component from the list
|
||||
/// </summary>
|
||||
/// <param name="UniqueLabel">unique label used to identify a component</param>
|
||||
public void RemoveComponent(string UniqueLabel)
|
||||
{
|
||||
int nIndex = GetIndexForComponent(UniqueLabel);
|
||||
if (nIndex != -1)
|
||||
m_ArrayList.RemoveAt(nIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if a component already exists
|
||||
/// </summary>
|
||||
/// <param name="UniqueLabel">unique name identifying the component</param>
|
||||
/// <returns>true for yes, no otherwise</returns>
|
||||
public bool ComponentExists(string UniqueLabel)
|
||||
{
|
||||
return (GetIndexForComponent(UniqueLabel) != -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the component for the specified UniqueLabel
|
||||
/// </summary>
|
||||
/// <param name="UniqueLabel">unique name identifying the component</param>
|
||||
/// <returns>the Component for the Label, or null if not found</returns>
|
||||
public Component GetComponent(string UniqueLabel)
|
||||
{
|
||||
int nIndex = GetIndexForComponent(UniqueLabel);
|
||||
if (nIndex != -1)
|
||||
return (Component) m_ArrayList[nIndex];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal & Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// gets the index in the array list for the specified component
|
||||
/// </summary>
|
||||
/// <param name="UniqueLabel">unique name identifying the component</param>
|
||||
/// <returns>index >= 0 or -1 if not found</returns>
|
||||
private int GetIndexForComponent(string UniqueLabel)
|
||||
{
|
||||
for (int i = 0; i < m_ArrayList.Count; ++i)
|
||||
{
|
||||
Component component = (Component)m_ArrayList[i];
|
||||
if (String.Compare(component.UniqueLabel, UniqueLabel, true) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// specify the Component
|
||||
/// </summary>
|
||||
public class Component : IComparable
|
||||
{
|
||||
public Component() { }
|
||||
public Component(string UniqueLabel, string Version, string FileName) { this.UniqueLabel = UniqueLabel; this.Version = Version; this.FileName = FileName; }
|
||||
|
||||
[XmlText]
|
||||
public string FileName = "";
|
||||
|
||||
/// <summary>
|
||||
/// In case a component has multiple files, seperated by a ';', internally we should always call this
|
||||
/// </summary>
|
||||
public string[] FileNames
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!String.IsNullOrEmpty(FileName))
|
||||
{
|
||||
if (FileName.Contains(';'))
|
||||
return FileName.Split(';');
|
||||
else
|
||||
return new string[] { FileName };
|
||||
}
|
||||
return new string[] { };
|
||||
}
|
||||
}
|
||||
|
||||
[XmlAttribute("UniqueLabel")]
|
||||
public string UniqueLabel = "";
|
||||
|
||||
[XmlAttribute("Version")]
|
||||
public string Version = "";
|
||||
|
||||
/// <summary>
|
||||
/// In case a component has multiple files, seperated by a ';', internally we should always call this
|
||||
/// </summary>
|
||||
public string[] TempFileNamesNPath
|
||||
{
|
||||
get
|
||||
{
|
||||
string[] files = FileNames;
|
||||
List<string> tFiles = new List<string>();
|
||||
if (files != null)
|
||||
{
|
||||
string strPath = PathNaming.PathEndsWithSlash(Path.GetTempPath());
|
||||
foreach (string file in files)
|
||||
tFiles.Add(strPath + file);
|
||||
return tFiles.ToArray();
|
||||
}
|
||||
return new string[] { };
|
||||
}
|
||||
}
|
||||
|
||||
#region IComparable Members
|
||||
|
||||
/// <summary>
|
||||
/// Compares the Components Unique Label and Version
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
if (obj is Component)
|
||||
{
|
||||
Component c = (Component)obj;
|
||||
int nCompare = String.Compare(this.UniqueLabel, c.UniqueLabel, true);
|
||||
if (nCompare == 0)
|
||||
nCompare = String.Compare(this.Version, c.Version, true);
|
||||
return nCompare;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("object is not a Component");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
277
@integrate/Component.All/Component_Binary_Manager.cs
Normal file
277
@integrate/Component.All/Component_Binary_Manager.cs
Normal file
@@ -0,0 +1,277 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BridgeConnector.Lib.File;
|
||||
using System.Xml.Serialization;
|
||||
using System.Collections;
|
||||
using BridgeConnector.Lib.XML;
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using BridgeConnector.Lib.Tools;
|
||||
using BridgeConnector.Lib.Assembly;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for extracting the Components that are embedded in this dll
|
||||
/// into the temporary directory for the installer to consume
|
||||
/// </summary>
|
||||
public class Component_Binary_Manager : IDisposable, IManageComponents
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
private Dictionary<string, Assembly> _componentsLoaded = new Dictionary<string, Assembly>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public Component_Binary_Manager()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~Component_Binary_Manager()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IManageComponents Members
|
||||
|
||||
/// <summary>
|
||||
/// Checks if there are Newer Components embedded then that were installed on the system
|
||||
/// </summary>
|
||||
/// <returns>true, if newer components were found, false otherwise</returns>
|
||||
public bool AreNewerComponentsAvailable()
|
||||
{
|
||||
//# If nothing is installed, no need to continue
|
||||
if (GetAllInstalledComponents() == null)
|
||||
return true;
|
||||
|
||||
// if the lengths don't match, something must get installed
|
||||
if (GetAllInstalledComponents().Length != GetAllEmbeddedComponents().Length)
|
||||
return true;
|
||||
|
||||
// # Otherwise, let's determine 1 by 1
|
||||
foreach (ComponentConfig.Component component in GetAllEmbeddedComponents())
|
||||
{
|
||||
int nIndex = Common.GetIndexForComponentUniqueLabel(component.UniqueLabel, GetAllInstalledComponents());
|
||||
if (nIndex == -1)
|
||||
return true;
|
||||
else if(GetAllInstalledComponents()[nIndex].CompareTo(component) != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Component Definition containing the temporary file (extracted component)
|
||||
/// for all Newer components found on the system
|
||||
/// </summary>
|
||||
/// <param name="setupEventObj">Setup Event Object is passed, for component manager to pass down to it's components</param>
|
||||
/// <returns>a list of newer binary components, or empty list for none</returns>
|
||||
public IInstallComponent[] GetNewerComponents(ref SetupEvents setupEventObj)
|
||||
{
|
||||
// # Extract all, or let's determine 1 by 1 and extract
|
||||
bool bInstalledCompsFound = (GetAllInstalledComponents() != null);
|
||||
foreach (ComponentConfig.Component component in GetAllEmbeddedComponents())
|
||||
{
|
||||
bool bExtract = true;
|
||||
if (bInstalledCompsFound)
|
||||
{
|
||||
int nIndex = Common.GetIndexForComponentUniqueLabel(component.UniqueLabel, GetAllInstalledComponents());
|
||||
if (nIndex != -1)
|
||||
bExtract = (GetAllInstalledComponents()[nIndex].CompareTo(component) != 0);
|
||||
}
|
||||
|
||||
// mark component for Installation * Extract to File System *
|
||||
if (bExtract)
|
||||
{
|
||||
if (!ExtractComponentFromResourceToTempFileLocation(component))
|
||||
Common.Log.Error(String.Format("Failed to Extract Component {0}", component.UniqueLabel));
|
||||
}
|
||||
}
|
||||
|
||||
List<IInstallComponent> ComponentsToInstall = new List<IInstallComponent>();
|
||||
if (_componentsLoaded.Count > 0)
|
||||
{
|
||||
foreach(Assembly asm in _componentsLoaded.Values)
|
||||
{
|
||||
IInstallComponent installComp = null;
|
||||
Type[] types = asm.GetTypes();
|
||||
foreach (Type t in types)
|
||||
{
|
||||
if (t.GetInterface(typeof(IInstallComponent).Name) != null)
|
||||
{
|
||||
installComp = (IInstallComponent) asm.CreateInstance(t.FullName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check IInstallComponent was found
|
||||
if (installComp == null)
|
||||
{
|
||||
Common.Log.Error(String.Format("Component {0} contains no IInstallComponent Definition.", AssemblyW.GetAssemblyName(asm)));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if class also implements ISetup
|
||||
if(installComp is ISetup)
|
||||
((ISetup) installComp).ComponentLoaded(ref setupEventObj);
|
||||
|
||||
// Add to Install Components
|
||||
ComponentsToInstall.Add(installComp);
|
||||
}
|
||||
}
|
||||
return ComponentsToInstall.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed components, in order to uninstall
|
||||
/// </summary>
|
||||
/// <returns>a list of all installed components, null otherwise</returns>
|
||||
public IInstallComponent[] GetAllInstalledComponents(string ComponentsSeperatedbySemiColonOrBlankForAll, ref SetupEvents setupEventObj)
|
||||
{
|
||||
// TO DO:
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed components
|
||||
/// </summary>
|
||||
/// <returns>a list of all installed components, null otherwise</returns>
|
||||
public ComponentConfig.Component[] GetAllInstalledComponents()
|
||||
{
|
||||
if (Common.InstalledConfig != null && Common.InstalledConfig.BinaryComponents.Components.Length > 0)
|
||||
return Common.InstalledConfig.BinaryComponents.Components;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed componentsW
|
||||
/// </summary>
|
||||
/// <returns>a list of all installed componentsW, null otherwise</returns>
|
||||
public ComponentConfig.ComponentW GetAllInstalledComponentsW()
|
||||
{
|
||||
return Common.InstalledConfig.BinaryComponents;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all Embedded components
|
||||
/// </summary>
|
||||
/// <returns>a list of all embedded components, null otherwise</returns>
|
||||
public ComponentConfig.Component[] GetAllEmbeddedComponents()
|
||||
{
|
||||
if (Common.EmbeddedConfig != null && Common.EmbeddedConfig.BinaryComponents.Components.Length > 0)
|
||||
return Common.EmbeddedConfig.BinaryComponents.Components;
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Private Helper to physically extract the bits from the resource and write them to a temporary
|
||||
/// file location
|
||||
/// </summary>
|
||||
/// <param name="component">Component, whose files are to be extracted</param>
|
||||
/// <returns>true, if successful, false otherwise</returns>
|
||||
private bool ExtractComponentFromResourceToTempFileLocation(ComponentConfig.Component component)
|
||||
{
|
||||
if (component != null)
|
||||
{
|
||||
// Extract the component to the Temp Directory,
|
||||
// if it is not already there...
|
||||
for (int i = 0; i < component.FileNames.Length; ++i)
|
||||
{
|
||||
// First try loading the assembly
|
||||
string asmName = "Component.Binary." + component.UniqueLabel;
|
||||
Assembly asm = Assembly.Load(asmName);
|
||||
if (asm == null)
|
||||
return false;
|
||||
else
|
||||
_componentsLoaded[component.UniqueLabel] = asm; // <- imp
|
||||
string FileName = component.FileNames[i];
|
||||
string TempFileNameNPath = component.TempFileNamesNPath[i];
|
||||
if (!File.Exists(TempFileNameNPath))
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(asm.GetManifestResourceStream(asmName + "." + FileName)))
|
||||
using (BinaryWriter bw = new BinaryWriter(new FileStream(TempFileNameNPath, FileMode.Create)))
|
||||
{
|
||||
byte[] buffer = new byte[64 * 1024];
|
||||
int numread = br.Read(buffer, 0, buffer.Length);
|
||||
while (numread > 0)
|
||||
{
|
||||
bw.Write(buffer, 0, numread);
|
||||
numread = br.Read(buffer, 0, buffer.Length);
|
||||
}
|
||||
bw.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of all extracted files
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// Use SupressFinalize in case a subclass
|
||||
// of this type implements a finalizer
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure to conserve disk space, to delete all files that were extracted
|
||||
/// by this program
|
||||
/// </summary>
|
||||
/// <param name="disposing">if true, delete all files extracted by this dll</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// When Disposing, Delete all Temporary Files on the System that may exist
|
||||
foreach (ComponentConfig.Component component in GetAllEmbeddedComponents())
|
||||
{
|
||||
foreach (string tFileNameNPath in component.TempFileNamesNPath)
|
||||
{
|
||||
if (File.Exists(tFileNameNPath))
|
||||
File.Delete(tFileNameNPath);
|
||||
}
|
||||
}
|
||||
|
||||
_componentsLoaded.Clear();
|
||||
_componentsLoaded = null;
|
||||
}
|
||||
|
||||
// Indicate that the instance has been disposed.
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
213
@integrate/Component.All/Component_Setup_Manager.cs
Normal file
213
@integrate/Component.All/Component_Setup_Manager.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using BridgeConnector.Lib.Assembly;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for working with setup components which don't require any special treatment
|
||||
/// </summary>
|
||||
public class Component_Setup_Manager : IDisposable, IManageComponents
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
private Dictionary<string, Assembly> _componentsLoaded = new Dictionary<string, Assembly>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public Component_Setup_Manager()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~Component_Setup_Manager()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IManageComponents Members
|
||||
|
||||
/// <summary>
|
||||
/// Checks if there are Newer Components embedded then that were installed on the system
|
||||
/// </summary>
|
||||
/// <returns>true, if newer components were found, false otherwise</returns>
|
||||
public bool AreNewerComponentsAvailable()
|
||||
{
|
||||
//# If nothing is installed, no need to continue
|
||||
if (GetAllInstalledComponents() == null)
|
||||
return true;
|
||||
|
||||
// if the lengths don't match, something must get installed
|
||||
if (GetAllInstalledComponents().Length != GetAllEmbeddedComponents().Length)
|
||||
return true;
|
||||
|
||||
// # Otherwise, let's determine 1 by 1
|
||||
foreach (ComponentConfig.Component component in GetAllEmbeddedComponents())
|
||||
{
|
||||
int nIndex = Common.GetIndexForComponentUniqueLabel(component.UniqueLabel, GetAllInstalledComponents());
|
||||
if (nIndex == -1)
|
||||
return true;
|
||||
else if (GetAllInstalledComponents()[nIndex].CompareTo(component) != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Component Definitions for all Newer components found on the system
|
||||
/// </summary>
|
||||
/// <returns>a list of newer setup components, or empty list for none</returns>
|
||||
public IInstallComponent[] GetNewerComponents(ref SetupEvents setupEventObj)
|
||||
{
|
||||
// # Extract all, or let's determine 1 by 1 and extract
|
||||
bool bInstalledCompsFound = (GetAllInstalledComponents() != null);
|
||||
foreach (ComponentConfig.Component component in GetAllEmbeddedComponents())
|
||||
{
|
||||
bool bInstall = true;
|
||||
if (bInstalledCompsFound)
|
||||
{
|
||||
int nIndex = Common.GetIndexForComponentUniqueLabel(component.UniqueLabel, GetAllInstalledComponents());
|
||||
if (nIndex != -1)
|
||||
bInstall = (GetAllInstalledComponents()[nIndex].CompareTo(component) != 0);
|
||||
}
|
||||
|
||||
// mark component for Installation
|
||||
if (bInstall)
|
||||
{
|
||||
string asmName = "Component.Setup." + component.UniqueLabel;
|
||||
_componentsLoaded[component.UniqueLabel] = Assembly.Load(asmName);
|
||||
}
|
||||
}
|
||||
|
||||
List<IInstallComponent> ComponentsToInstall = new List<IInstallComponent>();
|
||||
if (_componentsLoaded.Count > 0)
|
||||
{
|
||||
foreach (Assembly asm in _componentsLoaded.Values)
|
||||
{
|
||||
IInstallComponent installComp = null;
|
||||
Type[] types = asm.GetTypes();
|
||||
foreach (Type t in types)
|
||||
{
|
||||
if (t.GetInterface(typeof(IInstallComponent).Name) != null)
|
||||
{
|
||||
installComp = (IInstallComponent)asm.CreateInstance(t.FullName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check IInstallComponent was found
|
||||
if (installComp == null)
|
||||
{
|
||||
Common.Log.Error(String.Format("Component {0} contains no IInstallComponent Definition.", AssemblyW.GetAssemblyName(asm)));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if class also implements ISetup
|
||||
if (installComp is ISetup)
|
||||
((ISetup)installComp).ComponentLoaded(ref setupEventObj);
|
||||
|
||||
// Add to Install Components
|
||||
ComponentsToInstall.Add(installComp);
|
||||
}
|
||||
}
|
||||
return ComponentsToInstall.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed components, in order to uninstall
|
||||
/// </summary>
|
||||
/// <returns>a list of all installed components, null otherwise</returns>
|
||||
public IInstallComponent[] GetAllInstalledComponents(string ComponentsSeperatedbySemiColonOrBlankForAll, ref SetupEvents setupEventObj)
|
||||
{
|
||||
// TO DO:
|
||||
|
||||
//string[] ComponentsUniqueLabels = null;
|
||||
//if (!String.IsNullOrEmpty(ComponentsSeperatedbySemiColonOrBlankForAll))
|
||||
// ComponentsUniqueLabels = ComponentsSeperatedbySemiColonOrBlankForAll.Split(';');
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed components
|
||||
/// </summary>
|
||||
/// <returns>a list of all installed components, null otherwise</returns>
|
||||
public ComponentConfig.Component[] GetAllInstalledComponents()
|
||||
{
|
||||
if (Common.InstalledConfig != null && Common.InstalledConfig.SetupComponents.Components.Length > 0)
|
||||
return Common.InstalledConfig.SetupComponents.Components;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed componentsW
|
||||
/// </summary>
|
||||
/// <returns>a list of all installed componentsW, null otherwise</returns>
|
||||
public ComponentConfig.ComponentW GetAllInstalledComponentsW()
|
||||
{
|
||||
return Common.InstalledConfig.SetupComponents;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all Embedded components
|
||||
/// </summary>
|
||||
/// <returns>a list of all embedded components, null otherwise</returns>
|
||||
public ComponentConfig.Component[] GetAllEmbeddedComponents()
|
||||
{
|
||||
if (Common.EmbeddedConfig != null && Common.EmbeddedConfig.SetupComponents.Components.Length > 0)
|
||||
return Common.EmbeddedConfig.SetupComponents.Components;
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of all extracted files
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// Use SupressFinalize in case a subclass
|
||||
// of this type implements a finalizer
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure to conserve disk space, to delete all files that were extracted
|
||||
/// by this program
|
||||
/// </summary>
|
||||
/// <param name="disposing">if true, delete all files extracted by this dll</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_componentsLoaded.Clear();
|
||||
_componentsLoaded = null;
|
||||
}
|
||||
|
||||
// Indicate that the instance has been disposed.
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
13
@integrate/Component.All/EmbeddedComponentConfig.xml
Normal file
13
@integrate/Component.All/EmbeddedComponentConfig.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ComponentConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="BridgeConnect">
|
||||
<BinaryComponents>
|
||||
<Component UniqueLabel="Java" Version="1.6.0_27">jre-6u27-windows-i586-s.exe</Component>
|
||||
<Component UniqueLabel="PostgreSql" Version="9.1.1-1">postgresql-9.1.1-1-windows.exe</Component>
|
||||
<Component UniqueLabel="PostgreSql_Admin" Version="1.14.0">pgadmin3-1.14.0.msi</Component>
|
||||
<Component UniqueLabel="PostgreSql_Devart" Version="5.50.228.0">Devart.Data.dll;Devart.Data.PostgreSql.dll;Devart.Data.PostgreSql.xml;gacutil.exe;gacutil.exe.config</Component>
|
||||
<Component UniqueLabel="Mirth" Version="2.1.1.5490.b781">mirthconnect-2.1.1.5490.b781-windows.exe</Component>
|
||||
</BinaryComponents>
|
||||
<SetupComponents>
|
||||
<Component UniqueLabel="BridgeService" Version="1.0.0.0">BridgeService.exe</Component>
|
||||
</SetupComponents>
|
||||
</ComponentConfig>
|
||||
328
@integrate/Component.All/GenericInstaller.cs
Normal file
328
@integrate/Component.All/GenericInstaller.cs
Normal file
@@ -0,0 +1,328 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BridgeConnector.Lib.Thread;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// Calls GenericInstaller in order to perform an install/uninstall
|
||||
/// * Does so in a threaded fashion *
|
||||
/// </summary>
|
||||
public class GenericInstall
|
||||
{
|
||||
// Let the Caller know that a) the thread Completed b) it did so successfully
|
||||
public static bool s_PerformInstallCompleted = false;
|
||||
public static bool s_PerformInstallCompletedSuccessfully = false;
|
||||
|
||||
// Let the Caller know that a) the thread Completed b) it did so successfully
|
||||
public static bool s_PerformUninstallCompleted = false;
|
||||
public static bool s_PerformUninstallCompletedSuccessfully = false;
|
||||
|
||||
// Private ComponentMgmtObjects
|
||||
private static GenericInstaller<Component_Binary_Manager> s_binaryInstaller = null;
|
||||
private static GenericInstaller<Component_Setup_Manager> s_setupInstaller = null;
|
||||
private static SetupEvents s_SetupEvents = new SetupEvents();
|
||||
|
||||
/// <summary>
|
||||
/// Perform a Threaded Install
|
||||
/// </summary>
|
||||
public static void PerformInstall()
|
||||
{
|
||||
TStarter.ThreadMethod tMethod = delegate()
|
||||
{
|
||||
s_PerformInstallCompleted = false;
|
||||
s_PerformInstallCompletedSuccessfully = false;
|
||||
bool bBinaryInstallNeeded = false;
|
||||
bool bSetupInstallNeeded = false;
|
||||
|
||||
// # Let's see if we need to update/install Binary Components
|
||||
if(s_binaryInstaller == null)
|
||||
s_binaryInstaller = new GenericInstaller<Component_Binary_Manager>();
|
||||
bBinaryInstallNeeded = s_binaryInstaller.IsInstallNeeded(ref s_SetupEvents);
|
||||
|
||||
// # Let's see if we need to update/install Setup Components
|
||||
if(s_setupInstaller == null)
|
||||
s_setupInstaller = new GenericInstaller<Component_Setup_Manager>();
|
||||
bSetupInstallNeeded = s_setupInstaller.IsInstallNeeded(ref s_SetupEvents);
|
||||
|
||||
// # Let's Install, Baby...
|
||||
if (bBinaryInstallNeeded || bSetupInstallNeeded)
|
||||
{
|
||||
// # Trigger Start Install Event
|
||||
s_SetupEvents.Raise_Before_Install_Event();
|
||||
|
||||
bool bBinarySuccess = true;
|
||||
bool bSetupbSuccess = true;
|
||||
|
||||
// update/install Binary Components
|
||||
if (bBinaryInstallNeeded)
|
||||
bBinarySuccess = s_binaryInstaller.Install();
|
||||
|
||||
// update/install Setup Components
|
||||
if (bSetupInstallNeeded)
|
||||
bSetupbSuccess = s_setupInstaller.Install();
|
||||
|
||||
// # Trigger End Install Event
|
||||
if (bBinaryInstallNeeded || bSetupInstallNeeded)
|
||||
s_SetupEvents.Raise_After_Install_Event();
|
||||
|
||||
// # We fail if one of them fails
|
||||
s_PerformInstallCompletedSuccessfully = bBinarySuccess && bSetupbSuccess;
|
||||
}
|
||||
|
||||
// # Let External Callers know that this Thread Completed
|
||||
s_PerformInstallCompleted = true;
|
||||
};
|
||||
TStarter.StartThread(tMethod, "PerformInstall", System.Threading.ApartmentState.MTA, false, System.Threading.ThreadPriority.Normal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a Threaded Uninstall
|
||||
/// </summary>
|
||||
public static void PerformUninstall(string ComponentsSeperatedbySemiColonOrBlankForAll)
|
||||
{
|
||||
s_PerformUninstallCompleted = false;
|
||||
s_PerformUninstallCompletedSuccessfully = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this function to let every object know that either PerformInstall or PerformUninstall was called,
|
||||
/// the Gui then may have made some other modifications, and we are now completed
|
||||
/// </summary>
|
||||
public static void SetupMainCompleted()
|
||||
{
|
||||
// Notify all components that Setup is now complete
|
||||
s_SetupEvents.Raise_Ending_Setup_Event();
|
||||
|
||||
// # Imp! - We must call dispose on our Setup Objects
|
||||
if (s_binaryInstaller != null)
|
||||
{
|
||||
s_binaryInstaller.Dispose();
|
||||
s_binaryInstaller = null;
|
||||
}
|
||||
if (s_setupInstaller != null)
|
||||
{
|
||||
s_setupInstaller.Dispose();
|
||||
s_setupInstaller = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic Install Class used for IManageComponents
|
||||
/// </summary>
|
||||
/// <typeparam name="T">IManageComponents responsible for Installing</typeparam>
|
||||
public class GenericInstaller<T> : IDisposable where T : IManageComponents, IDisposable, new()
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private T _ComponentMGR = default(T);
|
||||
private IInstallComponent[] _ComponentsToPerformWorkOn = null;
|
||||
private bool _disposed = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Construct the T Object
|
||||
/// </summary>
|
||||
public GenericInstaller()
|
||||
{
|
||||
_ComponentMGR = new T();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~GenericInstaller()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="setupEventObj"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsInstallNeeded(ref SetupEvents setupEventObj)
|
||||
{
|
||||
if (_ComponentMGR.AreNewerComponentsAvailable())
|
||||
{
|
||||
Common.Log.Info(String.Format("Newer Components available for Type {0}.", _ComponentMGR.GetType().Name));
|
||||
_ComponentsToPerformWorkOn = _ComponentMGR.GetNewerComponents(ref setupEventObj);
|
||||
if (_ComponentsToPerformWorkOn != null && _ComponentsToPerformWorkOn.Length > 0)
|
||||
{
|
||||
Common.Log.Info(String.Format("Found {0} Newer Components.", _ComponentsToPerformWorkOn.Length));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Common.Log.Info(String.Format("No Newer Components available for Type {0}.", _ComponentMGR.GetType().Name));
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform Install on the IManageComponents specified when Constructing the GenericInstaller Object
|
||||
/// </summary>
|
||||
/// <returns>true if no error occurs, false otherwise</returns>
|
||||
public bool Install()
|
||||
{
|
||||
bool bErrorsOccured = false;
|
||||
List<ComponentConfig.Component> successfullyInstalledComponents = new List<ComponentConfig.Component>();
|
||||
if (_ComponentsToPerformWorkOn != null && _ComponentsToPerformWorkOn.Length > 0)
|
||||
{
|
||||
// # Start Install
|
||||
foreach (IInstallComponent installComp in _ComponentsToPerformWorkOn)
|
||||
{
|
||||
ComponentConfig.Component component = installComp.GetComponent();
|
||||
if (installComp.BEFORE_INSTALLING_COMPONENT())
|
||||
{
|
||||
Common.Log.Info(String.Format("Installing Component {0} with Version {1}.", component.UniqueLabel, component.Version));
|
||||
bool bInstallSuccess = installComp.INSTALL_COMPONENT();
|
||||
bInstallSuccess = bInstallSuccess && installComp.AFTER_INSTALLING_COMPONENT();
|
||||
if (bInstallSuccess)
|
||||
{
|
||||
Common.Log.Info(String.Format("Component {0} with version {1} was correctly installed.", component.UniqueLabel, component.Version));
|
||||
successfullyInstalledComponents.Add(component);
|
||||
}
|
||||
else
|
||||
{
|
||||
bErrorsOccured = true;
|
||||
string msg = String.Format("Component {0} with version {1} was not correctly installed.", component.UniqueLabel, component.Version);
|
||||
Common.Log.Error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// # End Install
|
||||
|
||||
// Add any installed components to the Installed Configuration
|
||||
foreach (ComponentConfig.Component component in successfullyInstalledComponents)
|
||||
_ComponentMGR.GetAllInstalledComponentsW().AddUpdateComponent(component.UniqueLabel, component.Version, component.FileName);
|
||||
|
||||
// Write out the installed Configuration
|
||||
Common.WriteOutChangesToInstalledConfig();
|
||||
}
|
||||
|
||||
Common.Log.Info(String.Format("Exiting Install() for Type {0} with bErrorsOccured set to = {1}", _ComponentMGR.GetType().Name, bErrorsOccured));
|
||||
return !bErrorsOccured;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="setupEventObj"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsUninstallNeeded(ref SetupEvents setupEventObj, string ComponentsSeperatedbySemiColonOrBlankForAll)
|
||||
{
|
||||
if(_ComponentMGR.GetAllInstalledComponents() != null)
|
||||
{
|
||||
Common.Log.Info(String.Format("Installed Components available for Type {0}.", _ComponentMGR.GetType().Name));
|
||||
_ComponentsToPerformWorkOn = _ComponentMGR.GetAllInstalledComponents(ComponentsSeperatedbySemiColonOrBlankForAll, ref setupEventObj);
|
||||
if (_ComponentsToPerformWorkOn != null && _ComponentsToPerformWorkOn.Length > 0)
|
||||
{
|
||||
Common.Log.Info(String.Format("Found {0} Components to Uninstall.", _ComponentsToPerformWorkOn.Length));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Common.Log.Info(String.Format("No Installed Components to Uninstall for Type {0}.", _ComponentMGR.GetType().Name));
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform Uninstall on the IManageComponents specified when Constructing the GenericInstaller Object
|
||||
/// </summary>
|
||||
/// <param name="ComponentsSeperatedbySemiColonOrBlankForAll">coma-seperated Unique Labels of components to uninstall, blank for all</param>
|
||||
/// <returns>true if no error occurs, false otherwise</returns>
|
||||
public bool Uninstall(ref SetupEvents setupEventObj, string ComponentsSeperatedbySemiColonOrBlankForAll)
|
||||
{
|
||||
bool bErrorsOccured = false;
|
||||
List<ComponentConfig.Component> successfullyUninstalledComponents = new List<ComponentConfig.Component>();
|
||||
if (_ComponentsToPerformWorkOn != null && _ComponentsToPerformWorkOn.Length > 0)
|
||||
{
|
||||
// # Start Uninstall
|
||||
foreach (IInstallComponent uninstallComp in _ComponentsToPerformWorkOn)
|
||||
{
|
||||
if (!uninstallComp.SUPPORTS_UNINSTALL()) // Not all components support uninstall * although they should, we should allow for this contigency
|
||||
continue;
|
||||
|
||||
ComponentConfig.Component component = uninstallComp.GetComponent();
|
||||
if (uninstallComp.BEFORE_UNINSTALLING_COMPONENT())
|
||||
{
|
||||
Common.Log.Info(String.Format("About to Uninstall Component {0} with Version {1}.", component.UniqueLabel, component.Version));
|
||||
bool bUninstallSuccess = uninstallComp.UNINSTALL_COMPONENT();
|
||||
if (!bUninstallSuccess)
|
||||
bErrorsOccured = true;
|
||||
|
||||
bUninstallSuccess = bUninstallSuccess && uninstallComp.AFTER_UNINSTALLING_COMPONENT();
|
||||
if (bUninstallSuccess)
|
||||
{
|
||||
Common.Log.Info(String.Format("Component {0} with version {1} was uninstalled.", component.UniqueLabel, component.Version));
|
||||
successfullyUninstalledComponents.Add(component);
|
||||
}
|
||||
else
|
||||
{
|
||||
string msg = String.Format("Component {0} with version {1} was not uninstalled.", component.UniqueLabel, component.Version);
|
||||
Common.Log.Error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// # End Uninstall
|
||||
|
||||
// Remove any uninstalled components from the Installed Configuration
|
||||
foreach (ComponentConfig.Component component in successfullyUninstalledComponents)
|
||||
_ComponentMGR.GetAllInstalledComponentsW().RemoveComponent(component.UniqueLabel);
|
||||
|
||||
// Write out the installed Configuration
|
||||
Common.WriteOutChangesToInstalledConfig();
|
||||
}
|
||||
|
||||
Common.Log.Info(String.Format("Exiting Uninstall() for Type {0} with bErrorsOccured set to = {1}", _ComponentMGR.GetType().Name, bErrorsOccured));
|
||||
return !bErrorsOccured;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of all extracted files
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// Use SupressFinalize in case a subclass
|
||||
// of this type implements a finalizer
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure to call Dispose on the ComponentMGR for it to perform any cleanup
|
||||
/// </summary>
|
||||
/// <param name="disposing">if true, dispose ComponentMGR</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_ComponentMGR.Dispose();
|
||||
_ComponentMGR = default(T);
|
||||
}
|
||||
|
||||
// Indicate that the instance has been disposed.
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
61
@integrate/Component.All/IInstallComponent.cs
Normal file
61
@integrate/Component.All/IInstallComponent.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// All Components that install themselves must support this interface
|
||||
/// </summary>
|
||||
public interface IInstallComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the Corresponding Component for this IInstallComponent
|
||||
/// </summary>
|
||||
/// <returns>the component for this IInstallCompoent</returns>
|
||||
ComponentConfig.Component GetComponent();
|
||||
|
||||
/// <summary>
|
||||
/// Used to determine if the component is needed to install
|
||||
/// </summary>
|
||||
/// <returns>true to continue to Install, false otherwise</returns>
|
||||
bool BEFORE_INSTALLING_COMPONENT();
|
||||
|
||||
/// <summary>
|
||||
/// Used to install a component
|
||||
/// </summary>
|
||||
/// <returns>true, if install was successful, false otherwise</returns>
|
||||
bool INSTALL_COMPONENT();
|
||||
|
||||
/// <summary>
|
||||
/// Used to do any validation after install occured
|
||||
/// </summary>
|
||||
/// <returns>true, if validation was successful, false otherwise</returns>
|
||||
bool AFTER_INSTALLING_COMPONENT();
|
||||
|
||||
/// <summary>
|
||||
/// Used to determine if the component supports uninstalling
|
||||
/// </summary>
|
||||
/// <returns>true, if component supports uninstalling, false otherwise</returns>
|
||||
bool SUPPORTS_UNINSTALL();
|
||||
|
||||
/// <summary>
|
||||
/// Used to determine if the component is needed to uninstall
|
||||
/// </summary>
|
||||
/// <returns>true to continue to uninstall, false otherwise</returns>
|
||||
bool BEFORE_UNINSTALLING_COMPONENT();
|
||||
|
||||
/// <summary>
|
||||
/// Used to uninstall a component
|
||||
/// </summary>
|
||||
/// <returns>true, if uninstall was successful, false otherwise</returns>
|
||||
bool UNINSTALL_COMPONENT();
|
||||
|
||||
/// <summary>
|
||||
/// Used to do any validation after uninstall occured
|
||||
/// </summary>
|
||||
/// <returns>true, if validation was successful, false otherwise</returns>
|
||||
bool AFTER_UNINSTALLING_COMPONENT();
|
||||
}
|
||||
}
|
||||
53
@integrate/Component.All/IManageComponents.cs
Normal file
53
@integrate/Component.All/IManageComponents.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the Binary and Setup Component Manager,
|
||||
/// could possible be reused later for a new Component Manager
|
||||
/// </summary>
|
||||
public interface IManageComponents
|
||||
{
|
||||
/// <summary>
|
||||
/// Quick Check to see if newer Components are available
|
||||
/// </summary>
|
||||
/// <returns>true, if newer components are available, false otherwise</returns>
|
||||
bool AreNewerComponentsAvailable();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of newer components that need to be installed
|
||||
/// </summary>
|
||||
/// <param name="setupEventObj">Setup Event Object is passed, for component manager to pass down to it's components</param>
|
||||
/// <returns>a list of newer components to install, null otherwise</returns>
|
||||
IInstallComponent[] GetNewerComponents(ref SetupEvents setupEventObj);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed components, in order to uninstall
|
||||
/// </summary>
|
||||
/// <param name="ComponentsSeperatedbySemiColonOrBlankForAll">Specify Component Filter</param>
|
||||
/// <param name="setupEventObj">Setup Event Object is passed, for component manager to pass down to it's components</param>
|
||||
/// <returns>a list of all installed components, null otherwise</returns>
|
||||
IInstallComponent[] GetAllInstalledComponents(string ComponentsSeperatedbySemiColonOrBlankForAll, ref SetupEvents setupEventObj);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed components
|
||||
/// </summary>
|
||||
/// <returns>a list of all installed components, null otherwise</returns>
|
||||
ComponentConfig.Component[] GetAllInstalledComponents();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all installed componentsW
|
||||
/// </summary>
|
||||
/// <returns>a list of all installed componentsW, null otherwise</returns>
|
||||
ComponentConfig.ComponentW GetAllInstalledComponentsW();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of all Embedded components
|
||||
/// </summary>
|
||||
/// <returns>a list of all embedded components, null otherwise</returns>
|
||||
ComponentConfig.Component[] GetAllEmbeddedComponents();
|
||||
}
|
||||
}
|
||||
112
@integrate/Component.All/ISetup.cs
Normal file
112
@integrate/Component.All/ISetup.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Component.All
|
||||
{
|
||||
/// <summary>
|
||||
/// Class is passed into ISetup ComponentLoaded() giving each component
|
||||
/// a chance to subscribe to it
|
||||
/// </summary>
|
||||
public class SetupEvents
|
||||
{
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Delegate used to handle Setup Events
|
||||
/// </summary>
|
||||
public delegate void SetupEvent();
|
||||
|
||||
/// <summary>
|
||||
/// Called after the entire Setup Application ends
|
||||
/// </summary>
|
||||
public event SetupEvent Ending_Setup;
|
||||
|
||||
/// <summary>
|
||||
/// Called before the entire Install Process Begins
|
||||
/// </summary>
|
||||
public event SetupEvent Before_Install;
|
||||
|
||||
/// <summary>
|
||||
/// Called after the entire Install Process ends
|
||||
/// </summary>
|
||||
public event SetupEvent After_Install;
|
||||
|
||||
/// <summary>
|
||||
/// Called before the entire Uninstall Process Begins
|
||||
/// </summary>
|
||||
public event SetupEvent Before_Uninstall;
|
||||
|
||||
/// <summary>
|
||||
/// Called after the entire Uninstall Process ends
|
||||
/// </summary>
|
||||
public event SetupEvent After_Uninstall;
|
||||
|
||||
#endregion
|
||||
|
||||
# region Event Raisers
|
||||
|
||||
/// <summary>
|
||||
/// Raise the Ending Setup Event
|
||||
/// </summary>
|
||||
public void Raise_Ending_Setup_Event()
|
||||
{
|
||||
if (Ending_Setup != null)
|
||||
Ending_Setup();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the Before Install Event
|
||||
/// </summary>
|
||||
public void Raise_Before_Install_Event()
|
||||
{
|
||||
if (Before_Install != null)
|
||||
Before_Install();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the After Install Event
|
||||
/// </summary>
|
||||
public void Raise_After_Install_Event()
|
||||
{
|
||||
if (After_Install != null)
|
||||
After_Install();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the Before Uninstall Event
|
||||
/// </summary>
|
||||
public void Raise_Before_Uninstall_Event()
|
||||
{
|
||||
if (Before_Uninstall != null)
|
||||
Before_Uninstall();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the After Uninstall Event
|
||||
/// </summary>
|
||||
public void Raise_After_Uninstall_Event()
|
||||
{
|
||||
if (After_Uninstall != null)
|
||||
After_Uninstall();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All Components that install themselves will implement this interface, if they are interested to
|
||||
/// listen to / Handle Setup Events
|
||||
/// </summary>
|
||||
public interface ISetup
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when the Component is loaded. Components are only loaded
|
||||
/// when an Install on them is iminent. The component has a chance to
|
||||
/// listen to/handle events in the setup process.
|
||||
/// </summary>
|
||||
void ComponentLoaded(ref SetupEvents subscribeToDesiredEvents);
|
||||
}
|
||||
|
||||
}
|
||||
36
@integrate/Component.All/Properties/AssemblyInfo.cs
Normal file
36
@integrate/Component.All/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Components")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("Components")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("ae8a648a-90cf-48ce-9b71-6e6b4cc417aa")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
7
@integrate/HiddenMainWindow.xaml
Normal file
7
@integrate/HiddenMainWindow.xaml
Normal file
@@ -0,0 +1,7 @@
|
||||
<Window x:Class="Watchdog.HiddenMainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Loaded="Window_Loaded" Closed="Window_Closed">
|
||||
<Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
1456
@integrate/HiddenMainWindow.xaml.cs
Normal file
1456
@integrate/HiddenMainWindow.xaml.cs
Normal file
File diff suppressed because it is too large
Load Diff
158
@integrate/InstallComponent.cs
Normal file
158
@integrate/InstallComponent.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Component.All;
|
||||
using BridgeConnector.Lib.File;
|
||||
|
||||
namespace Component.Binary.Mirth
|
||||
{
|
||||
public class InstallComponent : IInstallComponent , ISetup
|
||||
{
|
||||
public const string MIRTH_SERVICE_NAME = Common_MediLytec.MediLytecPoundDef.MIRTH_SERVICE_NAME;
|
||||
private const string POSTGRE_SERVICE_NAME = Common_MediLytec.MediLytecPoundDef.POSTGRE_SERVICE_NAME;
|
||||
|
||||
#region IInstallComponent Members
|
||||
|
||||
public ComponentConfig.Component GetComponent()
|
||||
{
|
||||
return Common.EmbeddedConfig.BinaryComponents.GetComponent("Mirth");
|
||||
}
|
||||
|
||||
public bool BEFORE_INSTALLING_COMPONENT()
|
||||
{
|
||||
bool bSuccess = Common.StopService(MIRTH_SERVICE_NAME);
|
||||
if (!bSuccess)
|
||||
{
|
||||
Common.Log.Error(String.Format("Failed to stop {0}", MIRTH_SERVICE_NAME));
|
||||
return false;
|
||||
}
|
||||
|
||||
string result = Common.RunCmdLine("netsh firewall set portopening tcp 8080 MirthConnectAdministrator ENABLE ALL");
|
||||
bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
|
||||
if (bSuccess)
|
||||
{
|
||||
result = Common.RunCmdLine("netsh firewall set portopening tcp 8443 MirthConnectServer ENABLE ALL");
|
||||
bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
|
||||
}
|
||||
if (bSuccess)
|
||||
{
|
||||
result = Common.RunCmdLine("netsh firewall set portopening tcp 1099 MirthConnectJMX ENABLE ALL");
|
||||
bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
|
||||
}
|
||||
if (!bSuccess)
|
||||
{
|
||||
Common.Log.Error(String.Format("Errors occured opening up ports for '{0}'", MIRTH_SERVICE_NAME));
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
public bool INSTALL_COMPONENT()
|
||||
{
|
||||
Common.PSetupSpwan(GetComponent().TempFileNamesNPath[0], "-q -overwrite");
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool AFTER_INSTALLING_COMPONENT()
|
||||
{
|
||||
if (!Common.ServiceExists(MIRTH_SERVICE_NAME))
|
||||
{
|
||||
Common.Log.Error(String.Format("Service '{0}' does not exist. Something went wrong with Setup", MIRTH_SERVICE_NAME));
|
||||
return false;
|
||||
}
|
||||
// Make sure Service is stopped
|
||||
Common.StopService(MIRTH_SERVICE_NAME);
|
||||
|
||||
// # Configure Mirth to work with PostgreSQL, if possible
|
||||
if (Common.ServiceExists(POSTGRE_SERVICE_NAME))
|
||||
{
|
||||
//SetupMirthToUsePostgreSQL("mirthdb", "postgres", "Clinical$1");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SUPPORTS_UNINSTALL()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool BEFORE_UNINSTALLING_COMPONENT()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UNINSTALL_COMPONENT()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool AFTER_UNINSTALLING_COMPONENT()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ISetup Members
|
||||
|
||||
public void ComponentLoaded(ref SetupEvents subscribeToDesiredEvents)
|
||||
{
|
||||
subscribeToDesiredEvents.Before_Install += new SetupEvents.SetupEvent(subscribeToDesiredEvents_Before_Install);
|
||||
subscribeToDesiredEvents.After_Install += new SetupEvents.SetupEvent(subscribeToDesiredEvents_After_Install);
|
||||
subscribeToDesiredEvents.Ending_Setup += new SetupEvents.SetupEvent(subscribeToDesiredEvents_Ending_Setup);
|
||||
}
|
||||
|
||||
void subscribeToDesiredEvents_Ending_Setup()
|
||||
{
|
||||
// Make Sure at the end that both Mirth and Postgresql are started
|
||||
Common.StartService(POSTGRE_SERVICE_NAME);
|
||||
Common.StartService(MIRTH_SERVICE_NAME);
|
||||
}
|
||||
|
||||
void subscribeToDesiredEvents_Before_Install()
|
||||
{
|
||||
}
|
||||
|
||||
void subscribeToDesiredEvents_After_Install()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Function is responsible fore writing Postgresql Information to the Mirth Configuration
|
||||
/// * The Mirth Service needs to be stopped/started for this configuration to take affect,
|
||||
/// ideally this should only be called with the mirth service stopped *
|
||||
/// </summary>
|
||||
private void SetupMirthToUsePostgreSQL(string dbname, string user, string password)
|
||||
{
|
||||
// Open Mirth Configuration
|
||||
LineReplacer replacer = new LineReplacer((Common.GetProgramFilesPathOnSystemWithEndSlash() + "Mirth Connect\\conf\\mirth.properties"), Encoding.ASCII);
|
||||
|
||||
LineReplace_Rule DBurl = new LineReplace_Rule();
|
||||
DBurl.StartsWith = "database.url =";
|
||||
DBurl.ReplaceLineWith = String.Format("database.url = jdbc:postgresql://localhost:5432/{0}", dbname);
|
||||
DBurl.Comparer = LineReplace_ComparerModifier.None;
|
||||
replacer.AddUpdateRule("DBurl", DBurl);
|
||||
|
||||
LineReplace_Rule DBuser = new LineReplace_Rule();
|
||||
DBuser.StartsWith = "database.username =";
|
||||
DBuser.ReplaceLineWith = String.Format("database.username = {0}", user);
|
||||
DBuser.Comparer = LineReplace_ComparerModifier.None;
|
||||
replacer.AddUpdateRule("DBuser", DBuser);
|
||||
|
||||
LineReplace_Rule DBpass = new LineReplace_Rule();
|
||||
DBpass.StartsWith = "database.password =";
|
||||
DBpass.ReplaceLineWith = String.Format("database.password = {0}", password);
|
||||
DBpass.Comparer = LineReplace_ComparerModifier.None;
|
||||
replacer.AddUpdateRule("DBpass", DBpass);
|
||||
|
||||
// Replace Lines in Mirth Configuration
|
||||
replacer.ReplaceLines();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
186
@integrate/InstallComponent2.cs
Normal file
186
@integrate/InstallComponent2.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Component.All;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Component.Binary.Java
|
||||
{
|
||||
public class InstallComponent : IInstallComponent , ISetup
|
||||
{
|
||||
#region IInstallComponent Members
|
||||
|
||||
/// <summary>
|
||||
/// Get the Component bound to this IInstallComponent
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ComponentConfig.Component GetComponent()
|
||||
{
|
||||
return Common.EmbeddedConfig.BinaryComponents.GetComponent("Java");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We only want to install Java if an earlier version is installed
|
||||
/// </summary>
|
||||
/// <returns>true, if an earlier version or none is installed, false otherwise</returns>
|
||||
public bool BEFORE_INSTALLING_COMPONENT()
|
||||
{
|
||||
// If we get here, just in case always just install the java version
|
||||
// to make sure everything works as expected
|
||||
|
||||
//string Version = GetLatestJavaVersionFromTheRegistry();
|
||||
//if (!String.IsNullOrEmpty(Version))
|
||||
//{
|
||||
// int nCompare = String.Compare(Version, GetComponent().Version);
|
||||
// if (nCompare < 0)
|
||||
// return true;
|
||||
// else
|
||||
// return false;
|
||||
//}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs Java on the system
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the Component installs, false otherwise</returns>
|
||||
public bool INSTALL_COMPONENT()
|
||||
{
|
||||
Common.PSetupSpwan(GetComponent().TempFileNamesNPath[0], "/s /v \"/qn ADDLOCAL=ALL IEXPLORER=1 REBOOT=Supress\"");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure that the version in the registry matches the component
|
||||
/// </summary>
|
||||
/// <returns>true, if the version in the registry matches what we installed, false otherwise</returns>
|
||||
public bool AFTER_INSTALLING_COMPONENT()
|
||||
{
|
||||
string Version = GetLatestJavaVersionFromTheRegistry();
|
||||
if (!String.IsNullOrEmpty(Version))
|
||||
{
|
||||
int nCompare = String.Compare(GetComponent().Version, Version);
|
||||
if (nCompare != 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check to see, if this component supports uninstalling
|
||||
/// </summary>
|
||||
/// <returns>true, if uninstall is supported, false otherwise</returns>
|
||||
public bool SUPPORTS_UNINSTALL()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if we can uninstall the java version
|
||||
/// </summary>
|
||||
/// <returns>true, if version is installed, false otherwise</returns>
|
||||
public bool BEFORE_UNINSTALLING_COMPONENT()
|
||||
{
|
||||
string[] Versions = GetAllJavaVersionFromTheRegistry();
|
||||
if (Versions != null && Versions.Length > 0)
|
||||
{
|
||||
if (Versions.Contains(GetComponent().Version))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uninstalls Java on the system
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the Component installs, false otherwise</returns>
|
||||
public bool UNINSTALL_COMPONENT()
|
||||
{
|
||||
Common.PSetupSpwan(GetComponent().TempFileNamesNPath[0], "/s /v \"/qn REBOOT=Supress\" /x");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check to make sure that the version we uninstalled doesn't exist anymore
|
||||
/// </summary>
|
||||
/// <returns>true if version was removed, false otherwise</returns>
|
||||
public bool AFTER_UNINSTALLING_COMPONENT()
|
||||
{
|
||||
string[] Versions = GetAllJavaVersionFromTheRegistry();
|
||||
if (Versions != null && Versions.Length > 0)
|
||||
{
|
||||
if (Versions.Contains(GetComponent().Version))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ISetup Members
|
||||
|
||||
public void ComponentLoaded(ref SetupEvents subscribeToDesiredEvents)
|
||||
{
|
||||
subscribeToDesiredEvents.Before_Install += new SetupEvents.SetupEvent(subscribeToDesiredEvents_Before_Install);
|
||||
subscribeToDesiredEvents.After_Install += new SetupEvents.SetupEvent(subscribeToDesiredEvents_After_Install);
|
||||
}
|
||||
|
||||
void subscribeToDesiredEvents_Before_Install()
|
||||
{
|
||||
}
|
||||
|
||||
void subscribeToDesiredEvents_After_Install()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Use this function to check the java version in the registry
|
||||
/// </summary>
|
||||
/// <returns>The Java Version found in the registry or String.Empty, if not found</returns>
|
||||
string GetLatestJavaVersionFromTheRegistry()
|
||||
{
|
||||
string[] Versions = GetAllJavaVersionFromTheRegistry();
|
||||
if (Versions != null && Versions.Length > 0)
|
||||
{
|
||||
string strVersion = Versions[Versions.Length - 1];
|
||||
if (!String.IsNullOrEmpty(strVersion))
|
||||
return strVersion;
|
||||
}
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this function to check all the java versions in the registry
|
||||
/// </summary>
|
||||
/// <returns>The Java Versions found in the registry or null, if none found</returns>
|
||||
string[] GetAllJavaVersionFromTheRegistry()
|
||||
{
|
||||
bool bIsJavaInstalled = false;
|
||||
try
|
||||
{
|
||||
RegistryKey reg = Registry.LocalMachine.OpenSubKey("Software\\JavaSoft\\Java Plug-in", false);
|
||||
bIsJavaInstalled = (reg != null);
|
||||
if(reg == null)
|
||||
reg = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\JavaSoft\\Java Plug-in", false);
|
||||
bIsJavaInstalled = (reg != null);
|
||||
if (bIsJavaInstalled)
|
||||
{
|
||||
string[] SubKeys = reg.GetSubKeyNames();
|
||||
if (SubKeys != null && SubKeys.Length > 0)
|
||||
return SubKeys;
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
254
@integrate/InstallComponent4.cs
Normal file
254
@integrate/InstallComponent4.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Component.All;
|
||||
using Microsoft.Win32;
|
||||
using BridgeConnector.Lib.Assembly;
|
||||
using System.IO;
|
||||
using BridgeConnector.Lib.XML;
|
||||
using BridgeConnector;
|
||||
|
||||
namespace Component.Setup.BridgeService
|
||||
{
|
||||
public class InstallComponent : IInstallComponent , ISetup
|
||||
{
|
||||
#region Private Helpers
|
||||
|
||||
public const string BRIDGE_SERVICE_TITLE = Common_MediLytec.MediLytecPoundDef.BRIDGE_SERVICE_TITLE;
|
||||
public const string BRIDGE_SERVICE_ASSEMBLY = Common_MediLytec.MediLytecPoundDef.BRIDGE_SERVICE_ASSEMBLY;
|
||||
public const string BRIDGE_SERVICE_NAME = Common_MediLytec.MediLytecPoundDef.BRIDGE_SERVICE_NAME;
|
||||
|
||||
/// <summary>
|
||||
/// Write Service Configuration to the ImagePath for the Service
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool WriteServiceConfigurationToServiceInRegistry(InstallConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (RegistryKey service = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\services\\" + BRIDGE_SERVICE_TITLE, true))
|
||||
{
|
||||
// # Determine Image Path Parameter
|
||||
string ImagePathParameter = "";
|
||||
switch (config)
|
||||
{
|
||||
case InstallConfig.LytecMD:
|
||||
ImagePathParameter = " /Lytec";
|
||||
break;
|
||||
|
||||
case InstallConfig.MedisoftClinical:
|
||||
ImagePathParameter = " /Medisoft";
|
||||
break;
|
||||
}
|
||||
|
||||
// # Set Image Path Parameter
|
||||
string serviceAssembly = "\"" + AssemblyW.SpecializedAssemblyInfo.GetAssemblyPath(AssemblyW.AssemblyST.Executing) + "\\" + BRIDGE_SERVICE_ASSEMBLY + "\"";
|
||||
service.SetValue("ImagePath", serviceAssembly + ImagePathParameter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IInstallComponent Members
|
||||
|
||||
public ComponentConfig.Component GetComponent()
|
||||
{
|
||||
return Common.EmbeddedConfig.SetupComponents.GetComponent("BridgeService");
|
||||
}
|
||||
|
||||
public bool BEFORE_INSTALLING_COMPONENT()
|
||||
{
|
||||
// Stop Service BRIDGE_SERVICE_NAME
|
||||
if (!Common.StopService(BRIDGE_SERVICE_NAME))
|
||||
{
|
||||
Common.Log.Error(String.Format("Couldn't stop the {0} Service.", BRIDGE_SERVICE_NAME));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the Service Configuration from the Registry
|
||||
InstallConfig config = Common_MediLytec.RetrieveInstallConfigFromRegistry();
|
||||
if (config == InstallConfig.LytecMD)
|
||||
{
|
||||
bool bSuccess = false;
|
||||
string result = Common.RunCmdLine("netsh firewall set portopening tcp 5000 BridgeService_LytecBridgeIn ENABLE ALL");
|
||||
bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
|
||||
if (bSuccess)
|
||||
{
|
||||
result = Common.RunCmdLine("netsh firewall set portopening tcp 5001 BridgeService_LytecMirthOut ENABLE ALL");
|
||||
bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
|
||||
}
|
||||
if (bSuccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Common.Log.Error(String.Format("Opening up ports for Lytec '{0}' failed", BRIDGE_SERVICE_NAME));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (config == InstallConfig.MedisoftClinical)
|
||||
{
|
||||
bool bSuccess = false;
|
||||
string result = Common.RunCmdLine("netsh firewall set portopening tcp 7000 BridgeService_MedisoftBridgeIn ENABLE ALL");
|
||||
bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
|
||||
if (bSuccess)
|
||||
{
|
||||
result = Common.RunCmdLine("netsh firewall set portopening tcp 7001 BridgeService_MedisoftMirthOut ENABLE ALL");
|
||||
bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
|
||||
}
|
||||
if (bSuccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Common.Log.Error(String.Format("Opening up ports for Medisoft '{0}' failed", BRIDGE_SERVICE_NAME));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool INSTALL_COMPONENT()
|
||||
{
|
||||
// Uninstall Bridge Service, if it exists, and re-install
|
||||
if (Common.ServiceExists(BRIDGE_SERVICE_NAME))
|
||||
UNINSTALL_COMPONENT();
|
||||
|
||||
string installUtil = Common.GetNetFrameworkUtilFileNameNPathFile("installutil.exe");
|
||||
string serviceAssembly = AssemblyW.SpecializedAssemblyInfo.GetAssemblyPath(AssemblyW.AssemblyST.Entry) + "\\" + BRIDGE_SERVICE_ASSEMBLY;
|
||||
if (!String.IsNullOrEmpty(installUtil))
|
||||
{
|
||||
Common.StopService(BRIDGE_SERVICE_NAME);
|
||||
string result = Common.RunCmdLine(installUtil + " \"" + serviceAssembly + "\"");
|
||||
bool bSuccess = !result.Contains("failed");
|
||||
if (bSuccess)
|
||||
{
|
||||
// Write the Service Configuration to the Registry
|
||||
InstallConfig config = Common_MediLytec.RetrieveInstallConfigFromRegistry();
|
||||
bSuccess = WriteServiceConfigurationToServiceInRegistry(config);
|
||||
}
|
||||
if (!bSuccess)
|
||||
{
|
||||
Common.Log.Error(String.Format("Errors Occured installing {0}.", BRIDGE_SERVICE_NAME));
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool AFTER_INSTALLING_COMPONENT()
|
||||
{
|
||||
// Make sure service exists
|
||||
if (!Common.ServiceExists(BRIDGE_SERVICE_NAME))
|
||||
{
|
||||
Common.Log.Error(String.Format("Service {0} does Not Exist. Install Failed", BRIDGE_SERVICE_NAME));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure Service is stopped
|
||||
Common.StopService(BRIDGE_SERVICE_NAME);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SUPPORTS_UNINSTALL()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool BEFORE_UNINSTALLING_COMPONENT()
|
||||
{
|
||||
// Stop Service BRIDGE_SERVICE_NAME
|
||||
if (!Common.StopService(BRIDGE_SERVICE_NAME))
|
||||
{
|
||||
Common.Log.Error(String.Format("Couldn't stop the {0} Service.", BRIDGE_SERVICE_NAME));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UNINSTALL_COMPONENT()
|
||||
{
|
||||
if (Common.ServiceExists(BRIDGE_SERVICE_NAME))
|
||||
{
|
||||
Common.StopService(BRIDGE_SERVICE_NAME);
|
||||
string installUtil = Common.GetNetFrameworkUtilFileNameNPathFile("installutil.exe");
|
||||
string serviceAssembly = AssemblyW.SpecializedAssemblyInfo.GetAssemblyPath(AssemblyW.AssemblyST.Entry) + "\\" + BRIDGE_SERVICE_ASSEMBLY;
|
||||
if (!String.IsNullOrEmpty(installUtil))
|
||||
{
|
||||
string result = Common.RunCmdLine(installUtil + " /u \"" + serviceAssembly + "\"");
|
||||
bool bSuccess = !result.Contains("failed");
|
||||
if(!bSuccess)
|
||||
Common.Log.Error(String.Format("Errors Occured uninstalling {0}.", BRIDGE_SERVICE_NAME));
|
||||
return bSuccess;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool AFTER_UNINSTALLING_COMPONENT()
|
||||
{
|
||||
if (Common.ServiceExists(BRIDGE_SERVICE_NAME))
|
||||
{
|
||||
Common.Log.Error(String.Format("Service {0} Still Exists. Uninstall Failed", BRIDGE_SERVICE_NAME));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ISetup Members
|
||||
|
||||
public void ComponentLoaded(ref SetupEvents subscribeToDesiredEvents)
|
||||
{
|
||||
subscribeToDesiredEvents.Before_Install += new SetupEvents.SetupEvent(subscribeToDesiredEvents_Before_Install);
|
||||
subscribeToDesiredEvents.After_Install += new SetupEvents.SetupEvent(subscribeToDesiredEvents_After_Install);
|
||||
subscribeToDesiredEvents.Ending_Setup += new SetupEvents.SetupEvent(subscribeToDesiredEvents_Ending_Setup);
|
||||
}
|
||||
|
||||
void subscribeToDesiredEvents_Ending_Setup()
|
||||
{
|
||||
if (Common.ServiceExists(BRIDGE_SERVICE_NAME))
|
||||
{
|
||||
string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\McKesson\\Bridge\\BridgeConfig.xml";
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XSerializer serialize = new XSerializer();
|
||||
XMLConfig config = serialize.ReadFromFile<XMLConfig>(path);
|
||||
if (config != null)
|
||||
{
|
||||
// Read the Service Configuration from the Registry
|
||||
InstallConfig sconfig = Common_MediLytec.RetrieveInstallConfigFromRegistry();
|
||||
if (sconfig == InstallConfig.LytecMD && !String.IsNullOrEmpty(config.DefaultMapping.Lytec))
|
||||
Common.StartService(BRIDGE_SERVICE_NAME);
|
||||
else if(sconfig == InstallConfig.MedisoftClinical && !String.IsNullOrEmpty(config.DefaultMapping.Medisoft))
|
||||
Common.StartService(BRIDGE_SERVICE_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subscribeToDesiredEvents_Before_Install()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void subscribeToDesiredEvents_After_Install()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
240
@integrate/Logging.cs
Normal file
240
@integrate/Logging.cs
Normal file
@@ -0,0 +1,240 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
// Log4Net Declarations
|
||||
using log4net.Appender;
|
||||
using log4net.Core;
|
||||
using log4net.Layout;
|
||||
using log4net.Config;
|
||||
using log4net;
|
||||
using Diag = System.Diagnostics;
|
||||
using BridgeConnector.Lib.Other;
|
||||
|
||||
namespace BridgeConnector.Lib.File
|
||||
{
|
||||
/// <summary>
|
||||
/// Logging Detail
|
||||
/// </summary>
|
||||
public enum Logging_Detail
|
||||
{
|
||||
NONE,
|
||||
ERROR,
|
||||
INFO,
|
||||
DEBUG
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to Configure a Logger Instance in the Logging Class via AddGlobalLoggerConfiguration()
|
||||
/// </summary>
|
||||
public struct Logging_Configuration
|
||||
{
|
||||
public string LogFileNameNPath;
|
||||
public Logging_Detail Detail;
|
||||
public bool UseExclusiveFileLock;
|
||||
public int maxFileSizeInMB;
|
||||
public int numOfBackupLogFiles;
|
||||
public string PatternLayout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is a Wrapper Object around Log4Net's Rolling File Appender.
|
||||
/// Use it by calling AddGlobalLoggerConfiguration() with a valid Logging Configuration.
|
||||
/// You can configure multipe Logger Instances distinguished by Name.
|
||||
/// subsequent calls can call GetLogger() with the named Logger instance to receive a valid logger object
|
||||
/// </summary>
|
||||
public class Logging
|
||||
{
|
||||
#region Private Static Members
|
||||
|
||||
private static Dictionary<string, Logging_Configuration> _loggerConfigurationMap = new Dictionary<string, Logging_Configuration>();
|
||||
private static Dictionary<string, ILog> _loggerObjects = new Dictionary<string, ILog>();
|
||||
private static bool s_IsVSHosted = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Construction
|
||||
|
||||
private Logging() { s_IsVSHosted = Diag.Process.GetCurrentProcess().ProcessName.Contains("vshost"); }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Members
|
||||
|
||||
internal ILog _Log4NetLog = null; // Initialized by GetLogger()
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Log Methods
|
||||
|
||||
public void Info(object message) { if (_Log4NetLog != null) _Log4NetLog.Info(MessageHeader() + message); }
|
||||
public void Info(object message, int nPlusMinus) { if (_Log4NetLog != null) _Log4NetLog.Info(MessageHeader(nPlusMinus) + message); }
|
||||
public void Info(object message, Exception exception) { if (_Log4NetLog != null) _Log4NetLog.Info(MessageHeader() + message, exception); }
|
||||
|
||||
public void Debug(object message) { if (_Log4NetLog != null) _Log4NetLog.Debug(MessageHeader() + message); }
|
||||
public void Debug(object message, int nPlusMinus) { if (_Log4NetLog != null) _Log4NetLog.Debug(MessageHeader(nPlusMinus) + message); }
|
||||
public void Debug(object message, Exception exception) { if (_Log4NetLog != null) _Log4NetLog.Debug(MessageHeader() + message, exception); }
|
||||
|
||||
public void Error(object message) { if (_Log4NetLog != null) _Log4NetLog.Error(MessageHeader() + message); }
|
||||
public void Error(object message, int nPlusMinus) { if (_Log4NetLog != null) _Log4NetLog.Error(MessageHeader(nPlusMinus) + message); }
|
||||
public void Error(object message, Exception exception) { if (_Log4NetLog != null) _Log4NetLog.Error(MessageHeader() + message, exception); }
|
||||
|
||||
public void Fatal(object message) { if (_Log4NetLog != null) _Log4NetLog.Fatal(MessageHeader() + message); }
|
||||
public void Fatal(object message, int nPlusMinus) { if (_Log4NetLog != null) _Log4NetLog.Fatal(MessageHeader(nPlusMinus) + message); }
|
||||
public void Fatal(object message, Exception exception) { if (_Log4NetLog != null) _Log4NetLog.Fatal(MessageHeader() + message, exception); }
|
||||
|
||||
/// <returns>
|
||||
/// Message Header to be shown on every log message
|
||||
/// </returns>
|
||||
private string MessageHeader()
|
||||
{
|
||||
if (s_IsVSHosted)
|
||||
return MessageHeader(0);
|
||||
else
|
||||
return StackWalker.GetMethodNameFromStack(-2) + "()- ";
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// Message Header to be shown on every log message
|
||||
/// </returns>
|
||||
/// <param name="nPlusMinus">Use this to add/substract from the base stack level you want to retrieve</param>
|
||||
private string MessageHeader(int nPlusMinus)
|
||||
{
|
||||
// When Running this from via VS it behaves differently then when
|
||||
// running it outside of it, when running it regularly, each foreach loop
|
||||
// is it's own stackframe! ~weird but true. Only use the nPlusMinus when not running
|
||||
// inside VS
|
||||
if(s_IsVSHosted)
|
||||
return StackWalker.GetMethodNameFromStack(nPlusMinus) + "()- ";
|
||||
else
|
||||
return StackWalker.GetMethodNameFromStack(nPlusMinus - 1) + "()- ";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Configuration and Logger Creation Methods
|
||||
|
||||
/// <summary>
|
||||
/// Used to add a new Configuration and Logger Instance onto a Static Map.
|
||||
/// Will create one logger instance per unique name.
|
||||
/// </summary>
|
||||
/// <param name="Name">a name for the logger instance</param>
|
||||
/// <param name="Configuration">a valid configuration to use on the instance</param>
|
||||
/// <returns>a logging object that can be used to log</returns>
|
||||
public static Logging AddGlobalLoggerConfiguration(string Name, Logging_Configuration Configuration)
|
||||
{
|
||||
// Must have a Valid Input
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
throw new ArgumentException("Name Is Invalid");
|
||||
|
||||
if (!_loggerObjects.Keys.Contains(Name.ToLower()))
|
||||
{
|
||||
// Create the Repository
|
||||
log4net.Repository.ILoggerRepository repository = LogManager.CreateRepository(Name.ToLower());
|
||||
|
||||
// Create FileAppender Configuration
|
||||
RollingFileAppender appender = RollingFileAppenderCreator(Configuration);
|
||||
|
||||
// Run the Configuration against the Repository
|
||||
BasicConfigurator.Configure(repository, appender);
|
||||
|
||||
// Add Configuration to our Static Map
|
||||
_loggerConfigurationMap[Name.ToLower()] = Configuration;
|
||||
|
||||
// Last, but not least, Create the new Logging Instance Object and Store it
|
||||
_loggerObjects[Name.ToLower()] = LogManager.GetLogger(Name.ToLower(), Name.ToLower());
|
||||
}
|
||||
|
||||
// Let the Caller get the Logging Object
|
||||
return GetLogger(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to retrieve a named logging instance that has already been created via a previous call
|
||||
/// to AddGlobalLoggerConfiguration().
|
||||
/// </summary>
|
||||
/// <param name="Name">a name for a previously created Logging instance</param>
|
||||
/// <returns>a Logging object that can be used to log</returns>
|
||||
public static Logging GetLogger(string Name)
|
||||
{
|
||||
if (_loggerObjects.Keys.Contains(Name.ToLower()))
|
||||
{
|
||||
Logging logger = new Logging();
|
||||
logger._Log4NetLog = _loggerObjects[Name.ToLower()];
|
||||
return logger;
|
||||
}
|
||||
else
|
||||
throw new ArgumentException("Must call AddGlobalLoggerConfiguration() with a Configuration Before calling this Function");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Static Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Log4Net RollingFileAppender with the specified configuration
|
||||
/// </summary>
|
||||
/// <param name="config">a valid configuration</param>
|
||||
/// <returns>a Log4Net RollingFileAppender Object</returns>
|
||||
private static RollingFileAppender RollingFileAppenderCreator(Logging_Configuration config)
|
||||
{
|
||||
#region Input Validation
|
||||
|
||||
if (config.maxFileSizeInMB <= 0)
|
||||
throw new ArgumentException("Logging_Configuration - Invalid maxFileSizeInMB");
|
||||
|
||||
if (config.numOfBackupLogFiles < 0)
|
||||
throw new ArgumentException("Logging_Configuration - Invalid numOfBackupLogFiles");
|
||||
|
||||
if (String.IsNullOrEmpty(config.LogFileNameNPath))
|
||||
throw new Exception("Logging_Configuration - Invalid LogFileNameNPath");
|
||||
|
||||
if (!Directory.Exists(Path.GetDirectoryName(config.LogFileNameNPath)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(config.LogFileNameNPath));
|
||||
|
||||
#endregion
|
||||
|
||||
// Create and Set Layout for FileAppender
|
||||
RollingFileAppender rfAppender = new RollingFileAppender();
|
||||
if (!String.IsNullOrEmpty(config.PatternLayout))
|
||||
rfAppender.Layout = new PatternLayout(config.PatternLayout);
|
||||
else
|
||||
rfAppender.Layout = new PatternLayout("%date{dd MMM HH:mm:ss,fff} [%thread] %level - %message%newline");
|
||||
//rfAppender.Layout = new PatternLayout("%date{dd MMM yyyy HH:mm:ss,fff} [%thread] %level %logger - %message%newline");
|
||||
|
||||
// Locking Minimal allows us to run Log4Net from multiple processes
|
||||
if (config.UseExclusiveFileLock)
|
||||
rfAppender.LockingModel = new FileAppender.ExclusiveLock();
|
||||
else
|
||||
rfAppender.LockingModel = new FileAppender.MinimalLock();
|
||||
|
||||
// Configure FileName and always set Appent to true
|
||||
rfAppender.File = config.LogFileNameNPath;
|
||||
rfAppender.AppendToFile = true;
|
||||
|
||||
// According to the listings on the blog site
|
||||
// http://blog.aggregatedintelligence.com/2009/08/log4net-logging-levels-available.html
|
||||
// Error, will log Error, Fatal
|
||||
// Info, will log Info, Error, and Fatal
|
||||
// Debug, will log Info, Error, Fatal and Debug
|
||||
if (config.Detail == Logging_Detail.NONE)
|
||||
rfAppender.Threshold = Level.Off;
|
||||
else if (config.Detail == Logging_Detail.ERROR)
|
||||
rfAppender.Threshold = Level.Error;
|
||||
else if (config.Detail == Logging_Detail.INFO)
|
||||
rfAppender.Threshold = Level.Info;
|
||||
else if (config.Detail == Logging_Detail.DEBUG)
|
||||
rfAppender.Threshold = Level.Debug;
|
||||
|
||||
rfAppender.MaximumFileSize = String.Format("{0}MB", config.maxFileSizeInMB);
|
||||
rfAppender.MaxSizeRollBackups = config.numOfBackupLogFiles;
|
||||
rfAppender.RollingStyle = RollingFileAppender.RollingMode.Size; // Setting to RollingMode.Size will make MaxSizeRollBackups work
|
||||
rfAppender.ActivateOptions();
|
||||
return rfAppender;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
482
@integrate/MsgBox.cs
Normal file
482
@integrate/MsgBox.cs
Normal file
@@ -0,0 +1,482 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Watchdog.WatchdogLib.Win32;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing;
|
||||
using System.ComponentModel;
|
||||
using WPFWin = System.Windows;
|
||||
using WPFWinInterop = System.Windows.Interop;
|
||||
|
||||
namespace Watchdog.WatchdogLib.WinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// MsgBox is a WindowsForms MessageBox that can be centered to the Parent
|
||||
/// </summary>
|
||||
public static class MsgBox
|
||||
{
|
||||
#region Private Static Members
|
||||
|
||||
private static User32.WindowsHookProc _hookProcDelegate = null;
|
||||
private static int _hHook = 0;
|
||||
private static string _title = null;
|
||||
private static string _msg = null;
|
||||
private static IntPtr _hIcon = IntPtr.Zero;
|
||||
private static bool _IsDesktopOwner = false;
|
||||
private static bool _ShowFatal = false;
|
||||
|
||||
// Delegate to make All Message Boxes Thread-Safe
|
||||
private delegate DialogResult ShowMsgBoxDelegate(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon, Icon TitleBarIcon);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public static Icon DefaultTitleBarIcon { get; set; }
|
||||
public static uint MaxNumberOfCharactersPerLine { get; set; }
|
||||
public const uint DefaultNumberOfCharactersPerLine = 62;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Header Properties
|
||||
|
||||
public static bool ShowHeader { get; set; }
|
||||
public static string MsgBox_ErrorHeader { get; set; }
|
||||
public static string MsgBox_FatalErrorHeader { get; set; }
|
||||
public static string MsgBox_WarningHeader { get; set; }
|
||||
public static string MsgBox_InfoHeader { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Footer Properties
|
||||
|
||||
public static bool ShowFooter { get; set; }
|
||||
public static string MsgBox_ErrorFooter { get; set; }
|
||||
public static string MsgBox_FatalErrorFooter { get; set; }
|
||||
public static string MsgBox_WarningFooter { get; set; }
|
||||
public static string MsgBox_InfoFooter { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Title Header Properties
|
||||
|
||||
public static bool ShowTitleHeader { get; set; }
|
||||
public static string MsgBox_ErrorTitleHeader { get; set; }
|
||||
public static string MsgBox_FatalErrorTitleHeader { get; set; }
|
||||
public static string MsgBox_WarningTitleHeader { get; set; }
|
||||
public static string MsgBox_InfoTitleHeader { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
static MsgBox()
|
||||
{
|
||||
DefaultTitleBarIcon = null;
|
||||
MaxNumberOfCharactersPerLine = DefaultNumberOfCharactersPerLine;
|
||||
|
||||
// Header Init
|
||||
MsgBox_FatalErrorHeader = String.Empty;
|
||||
MsgBox_ErrorHeader = String.Empty;
|
||||
MsgBox_WarningHeader = String.Empty;
|
||||
MsgBox_InfoHeader = String.Empty;
|
||||
ShowHeader = true;
|
||||
|
||||
// Footer Init
|
||||
MsgBox_FatalErrorFooter = String.Empty;
|
||||
MsgBox_ErrorFooter = String.Empty;
|
||||
MsgBox_WarningFooter = String.Empty;
|
||||
MsgBox_InfoFooter = String.Empty;
|
||||
ShowFooter = true;
|
||||
|
||||
// Title Header Init
|
||||
MsgBox_FatalErrorTitleHeader = String.Empty;
|
||||
MsgBox_ErrorTitleHeader = String.Empty;
|
||||
MsgBox_WarningTitleHeader = String.Empty;
|
||||
MsgBox_InfoTitleHeader = String.Empty;
|
||||
ShowTitleHeader = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Shows a custom Message Box (centered to parent), with the DefaultTitleBarIcon
|
||||
/// </summary>
|
||||
public static DialogResult Show(WPFWin.Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon)
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
WPFWinInterop.WindowInteropHelper interop = new WPFWinInterop.WindowInteropHelper(parent);
|
||||
if(interop.Handle != IntPtr.Zero)
|
||||
return Show(Watchdog.WatchdogLib.Win32.Convert.ConverthWndToIWin32Window(interop.Handle), Title, Text, MsgBoxButtons, MsgBoxIcon, DefaultTitleBarIcon);
|
||||
}
|
||||
return Show(Functions.GetDestopWindow(), Title, Text, MsgBoxButtons, MsgBoxIcon, DefaultTitleBarIcon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows a custom Message Box (centered to parent), with the DefaultTitleBarIcon
|
||||
/// </summary>
|
||||
public static DialogResult Show(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MsgBoxIcon, DefaultTitleBarIcon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows a custom Message Box (centered to Desktop), with the DefaultTitleBarIcon
|
||||
/// </summary>
|
||||
public static DialogResult Show(String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon)
|
||||
{
|
||||
return Show(Functions.GetDestopWindow(), Title, Text, MsgBoxButtons, MsgBoxIcon, DefaultTitleBarIcon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// *Main MessageBox Show Function* allows you to center the Message Box to the Parent
|
||||
/// </summary>
|
||||
/// <returns>Result of Dialog </returns>
|
||||
public static DialogResult Show(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon, Icon TitleBarIcon)
|
||||
{
|
||||
ISynchronizeInvoke InvokeObject = null;
|
||||
if (parent != null && parent is ISynchronizeInvoke)
|
||||
InvokeObject = (ISynchronizeInvoke)parent;
|
||||
|
||||
// Invoke if we need to * Make MessageBoxes generally Thread-safe *
|
||||
if ((InvokeObject != null) && InvokeObject.InvokeRequired)
|
||||
{
|
||||
DialogResult result = (DialogResult)InvokeObject.Invoke(new ShowMsgBoxDelegate(MsgBox.Show), new object[] { parent, Title, Text, MsgBoxButtons, MsgBoxIcon, TitleBarIcon });
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MsgBox.ShowInternal(parent, Text, Title, MsgBoxButtons, MsgBoxIcon, TitleBarIcon);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Methods Extended
|
||||
|
||||
/// <summary>
|
||||
/// Shows Warning MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowWarning(IWin32Window parent, String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowWarning(IWin32Window parent, String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Exclamation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Warning MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowWarning(String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowWarning(String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
return Show(Title, Text, MsgBoxButtons, MessageBoxIcon.Exclamation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Fatal Error MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowFatalError(IWin32Window parent, String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowFatalError(IWin32Window parent, String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
_ShowFatal = true;
|
||||
DialogResult dr = Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
_ShowFatal = false;
|
||||
return dr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Fatal Error MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowFatalError(String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowFatalError(String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
_ShowFatal = true;
|
||||
DialogResult dr = Show(Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
_ShowFatal = false;
|
||||
return dr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Error MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowError(IWin32Window parent, String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowError(IWin32Window parent, String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Error MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowError(String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowError(String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
return Show(Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Information MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowInfo(IWin32Window parent, String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowInfo(IWin32Window parent, String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Information MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowInfo(String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowInfo(String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
return Show(Title, Text, MsgBoxButtons, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Default MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowDefault(IWin32Window parent, String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowDefault(IWin32Window parent, String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Default MessageBox
|
||||
/// </summary>
|
||||
//public static DialogResult ShowDefault(String Text, String Title = "", MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
public static DialogResult ShowDefault(String Text, String Title, MessageBoxButtons MsgBoxButtons)
|
||||
{
|
||||
return Show(Title, Text, MsgBoxButtons, MessageBoxIcon.None);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="btns"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <param name="TitleBarIcon"></param>
|
||||
/// <returns></returns>
|
||||
private static DialogResult ShowInternal(IWin32Window owner, string msg, string title, MessageBoxButtons btns, MessageBoxIcon icon, Icon TitleBarIcon)
|
||||
{
|
||||
// Create a callback delegate
|
||||
_hookProcDelegate = new User32.WindowsHookProc(HookCallback);
|
||||
|
||||
#region Header Action
|
||||
if (ShowHeader)
|
||||
{
|
||||
if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_FatalErrorHeader) && _ShowFatal)
|
||||
msg = MsgBox_FatalErrorHeader + msg;
|
||||
else if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_ErrorHeader) && !_ShowFatal)
|
||||
msg = MsgBox_ErrorHeader + msg;
|
||||
else if (icon == MessageBoxIcon.Exclamation && !String.IsNullOrEmpty(MsgBox_WarningHeader))
|
||||
msg = MsgBox_WarningHeader + msg;
|
||||
else if (icon == MessageBoxIcon.Information && !String.IsNullOrEmpty(MsgBox_InfoHeader))
|
||||
msg = MsgBox_InfoHeader + msg;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Footer Action
|
||||
if (ShowFooter)
|
||||
{
|
||||
if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_FatalErrorFooter) && _ShowFatal)
|
||||
msg = msg + MsgBox_FatalErrorFooter;
|
||||
else if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_ErrorFooter) && !_ShowFatal)
|
||||
msg = msg + MsgBox_ErrorFooter;
|
||||
else if (icon == MessageBoxIcon.Exclamation && !String.IsNullOrEmpty(MsgBox_WarningFooter))
|
||||
msg = msg + MsgBox_WarningFooter;
|
||||
else if (icon == MessageBoxIcon.Information && !String.IsNullOrEmpty(MsgBox_InfoFooter))
|
||||
msg = msg + MsgBox_InfoFooter;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Title Header
|
||||
if (ShowTitleHeader)
|
||||
{
|
||||
if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_FatalErrorTitleHeader) && _ShowFatal)
|
||||
title = MsgBox_FatalErrorTitleHeader + ((!String.IsNullOrEmpty(title)) ? (" (" + title + ")") : "");
|
||||
else if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_ErrorTitleHeader) && !_ShowFatal)
|
||||
title = MsgBox_ErrorTitleHeader + ((!String.IsNullOrEmpty(title)) ? (" (" + title + ")") : "");
|
||||
else if (icon == MessageBoxIcon.Exclamation && !String.IsNullOrEmpty(MsgBox_WarningTitleHeader))
|
||||
title = MsgBox_WarningTitleHeader + ((!String.IsNullOrEmpty(title)) ? (" (" + title + ")") : "");
|
||||
else if (icon == MessageBoxIcon.Information && !String.IsNullOrEmpty(MsgBox_InfoTitleHeader))
|
||||
title = MsgBox_InfoTitleHeader + ((!String.IsNullOrEmpty(title)) ? (" (" + title + ")") : "");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Text Padding
|
||||
|
||||
// Stripe last \n, if exists
|
||||
if (!String.IsNullOrEmpty(msg) && (msg.Length > 0) && (msg[msg.Length - 1] == '\n'))
|
||||
msg = msg.Remove(msg.Length - 1);
|
||||
|
||||
// Make sure the text looks good, by using padding
|
||||
if (!String.IsNullOrEmpty(msg) && (msg.Length > 0) && (msg.Length < MaxNumberOfCharactersPerLine))
|
||||
{
|
||||
string[] lines = msg.Split('\n');
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
sb.Append(line.PadRight((int)MaxNumberOfCharactersPerLine));
|
||||
sb.Append("\n");
|
||||
}
|
||||
msg = sb.ToString();
|
||||
}
|
||||
else if (!String.IsNullOrEmpty(msg) && (msg.Length > 0) && (msg.Length > MaxNumberOfCharactersPerLine))
|
||||
{
|
||||
// Incredible and amazing Padding code
|
||||
string[] lines = msg.Split('\n');
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < lines.Length; ++i)
|
||||
{
|
||||
if (lines[i].Length < MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
sb.Append(lines[i].PadRight((int)MaxNumberOfCharactersPerLine));
|
||||
sb.Append("\n");
|
||||
}
|
||||
else if (lines[i].Length > MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
// truncate
|
||||
for (int j = 0; j < lines[i].Length; j = j + (int)MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
string strSub = lines[i].Substring(j, ((lines[i].Length - j) > (int)MaxNumberOfCharactersPerLine) ? (int)MaxNumberOfCharactersPerLine : (lines[i].Length - j));
|
||||
if (strSub.Length == (int)MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
sb.Append(strSub);
|
||||
sb.Append("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(strSub.PadRight((int)MaxNumberOfCharactersPerLine));
|
||||
sb.Append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(lines[i]);
|
||||
sb.Append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Write nicely formatted Message out
|
||||
msg = sb.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing, string is miracioulsy exactly correct
|
||||
}
|
||||
#endregion
|
||||
|
||||
// Remember the title & message that we'll look for.
|
||||
// The hook sees *all* windows, so we need to make sure we operate on the right one.
|
||||
_msg = msg;
|
||||
_title = title;
|
||||
|
||||
// if Owner is the Desktop Window
|
||||
_IsDesktopOwner = (owner.Handle == Functions.GetDestopWindow().Handle);
|
||||
|
||||
// Icon could not be present
|
||||
if (TitleBarIcon != null)
|
||||
_hIcon = TitleBarIcon.ToBitmap().GetHicon();
|
||||
|
||||
// Set the hook.
|
||||
// Suppress "GetCurrentThreadId() is deprecated" warning.
|
||||
// It's documented that Thread.ManagedThreadId doesn't work with SetWindowsHookEx()
|
||||
#pragma warning disable 0618
|
||||
_hHook = User32.SetWindowsHookEx(Definitions.WH_CBT, _hookProcDelegate, IntPtr.Zero, AppDomain.GetCurrentThreadId());
|
||||
#pragma warning restore 0618
|
||||
|
||||
// Pop a standard MessageBox. The hook will center it.
|
||||
DialogResult rslt = DialogResult.None;
|
||||
if (_IsDesktopOwner)
|
||||
rslt = MessageBox.Show(_msg, _title, btns, icon);
|
||||
else
|
||||
rslt = MessageBox.Show(owner, _msg, _title, btns, icon);
|
||||
|
||||
// Release hook, clean up (may have already occurred)
|
||||
Unhook();
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
private static void Unhook()
|
||||
{
|
||||
User32.UnhookWindowsHookEx(_hHook);
|
||||
_hHook = 0;
|
||||
_hookProcDelegate = null;
|
||||
_msg = null;
|
||||
_title = null;
|
||||
}
|
||||
|
||||
private static int HookCallback(int code, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
int hHook = _hHook; // Local copy for CallNextHookEx() JIC we release _hHook
|
||||
|
||||
// Look for HCBT_ACTIVATE, *not* HCBT_CREATEWND:
|
||||
// child controls haven't yet been created upon HCBT_CREATEWND.
|
||||
if (code == Definitions.HCBT_ACTIVATE)
|
||||
{
|
||||
string cls = Functions.GetWindowClassName(wParam);
|
||||
if (cls == "#32770") // MessageBoxes are Dialog boxes
|
||||
{
|
||||
string title = Functions.GetWindowText(wParam);
|
||||
string msg = Functions.GetDlgItemText(wParam, 0xFFFF); // -1 aka IDC_STATIC
|
||||
if ((title == _title) && (msg == _msg))
|
||||
{
|
||||
// Only Center the Window, if the Owner is NOT the Desktop
|
||||
if (!_IsDesktopOwner)
|
||||
CenterWindowOnParent(wParam);
|
||||
|
||||
Unhook(); // Release hook - we've done what we needed
|
||||
|
||||
// Now we also want to set the Icon on the Dialog
|
||||
if (_hIcon != IntPtr.Zero)
|
||||
{
|
||||
User32.SendMessage(wParam, (int)Definitions.WM.WM_SETICON, (IntPtr)1, _hIcon);
|
||||
User32.SendMessage(wParam, (int)Definitions.WM.WM_SETICON, (IntPtr)0, _hIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return User32.CallNextHookEx(hHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
// Boilerplate window-centering code.
|
||||
// Split out of HookCallback() for clarity.
|
||||
private static void CenterWindowOnParent(IntPtr hChildWnd)
|
||||
{
|
||||
// Get child (MessageBox) size
|
||||
Structures.RECT rcChild = new Structures.RECT();
|
||||
User32.GetWindowRect(hChildWnd, out rcChild);
|
||||
int cxChild = rcChild.right - rcChild.left;
|
||||
int cyChild = rcChild.bottom - rcChild.top;
|
||||
|
||||
// Get parent (Form) size & location
|
||||
IntPtr hParent = User32.GetParent(hChildWnd);
|
||||
Structures.RECT rcParent = new Structures.RECT();
|
||||
User32.GetWindowRect(hParent, out rcParent);
|
||||
int cxParent = rcParent.right - rcParent.left;
|
||||
int cyParent = rcParent.bottom - rcParent.top;
|
||||
|
||||
// Center the MessageBox on the Form
|
||||
int x = rcParent.left + (cxParent - cxChild) / 2;
|
||||
int y = rcParent.top + (cyParent - cyChild) / 2;
|
||||
uint uFlags = 0x15; // SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE;
|
||||
User32.SetWindowPos(hChildWnd, IntPtr.Zero, x, y, 0, 0, uFlags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
12
@integrate/README.txt
Normal file
12
@integrate/README.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
Things to go over
|
||||
|
||||
File->Logging.cs
|
||||
Process->PStarter.cs
|
||||
Thread->SingleThreadTimer.cs (new)
|
||||
Watchdog->SysTray.cs
|
||||
Watchdog->MsgBox.cs
|
||||
Watchdog->Timer.cs
|
||||
Watchdog->Installer.cs (new)
|
||||
Watchdog->CHMFile.cs (new)
|
||||
|
||||
|
||||
120
@integrate/ResxHelper.cs
Normal file
120
@integrate/ResxHelper.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using Watchdog.WatchdogLib.Assembly;
|
||||
|
||||
namespace Watchdog
|
||||
{
|
||||
// ResxTypes
|
||||
public enum Resx
|
||||
{
|
||||
AppResx,
|
||||
}
|
||||
|
||||
#region ResxHelper Wrapper Classes
|
||||
|
||||
/// <summary>
|
||||
/// AppResx Wrapper String Resource Value Functions
|
||||
/// </summary>
|
||||
public static class AppResx
|
||||
{
|
||||
public static string GetString(string name)
|
||||
{
|
||||
return ResxHelper.GetStringValue(Resx.AppResx, name);
|
||||
}
|
||||
public static string GetStringFormated(string name, params object[] args)
|
||||
{
|
||||
return ResxHelper.GetStringValueFormated(Resx.AppResx, name, args);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Allows External Callers To Quickly gain access to the Resources Contained in this Assembly
|
||||
/// </summary>
|
||||
public static class ResxHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Private static Dictionary Map of Resource Managers
|
||||
/// </summary>
|
||||
private static Dictionary<Resx, ResourceManager> _ResourceMap = new Dictionary<Resx, ResourceManager>();
|
||||
|
||||
/// <summary>
|
||||
/// Static Constructor, iterates through the enumerations and loads resourceManagers internally
|
||||
/// </summary>
|
||||
static ResxHelper()
|
||||
{
|
||||
//string[] resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
||||
//~we shouldn't be doing this on filename (filename could change)
|
||||
//string curAsmName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().ManifestModule.Name);
|
||||
string curAsmName = AssemblyW.GetAssemblyName(AssemblyW.AssemblyST.Entry);
|
||||
|
||||
// Create a ResourceManager for each Resource Type in this Assembly
|
||||
foreach (string ResxName in Enum.GetNames(typeof(Resx)))
|
||||
_ResourceMap.Add((Resx)Enum.Parse(typeof(Resx), ResxName), new ResourceManager((curAsmName + "." + ResxName), Assembly.GetExecutingAssembly()));
|
||||
}
|
||||
|
||||
#region String Resource Value Functions
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Value of a String Resource via GetString()
|
||||
/// </summary>
|
||||
/// <param name="resx">Reource Type to Access</param>
|
||||
/// <param name="Name">Name of String Resource to get</param>
|
||||
/// <returns>the value of the resource, or "" if not found/Error Occured</returns>
|
||||
public static string GetStringValue(Resx resx, string Name)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Name))
|
||||
{
|
||||
string Value = PreserverFormating(_ResourceMap[resx].GetString(Name));
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Formated String Value of a String Resource via GetString()
|
||||
/// </summary>
|
||||
/// <param name="resx">Reource Type to Access</param>
|
||||
/// <param name="Name">Name of String Resource to get</param>
|
||||
/// <param name="args">Arguments to pass into String.Format()</param>
|
||||
/// <returns>the value of the resource, or "" if not found/Error Occured</returns>
|
||||
public static string GetStringValueFormated(Resx resx, string Name, params object[] args)
|
||||
{
|
||||
String retVal = GetStringValue(resx, Name);
|
||||
if (!String.IsNullOrEmpty(retVal))
|
||||
return String.Format(retVal, args);
|
||||
else
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// we want to preserver formating using '\' characters that are in the resource
|
||||
/// </summary>
|
||||
/// <param name="Name">a string value retrieved from the resource</param>
|
||||
/// <returns>a string that preserves formatting</returns>
|
||||
private static string PreserverFormating(string Value)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Value))
|
||||
{
|
||||
Value = Value.Replace("\\N", "\n");
|
||||
Value = Value.Replace("\\n", "\n");
|
||||
Value = Value.Replace("\\T", "\t");
|
||||
Value = Value.Replace("\\t", "\t");
|
||||
return Value;
|
||||
}
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
1057
@integrate/Settings.cs
Normal file
1057
@integrate/Settings.cs
Normal file
File diff suppressed because it is too large
Load Diff
24
@integrate/Snippets.txt
Normal file
24
@integrate/Snippets.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
private string GetDefaultBrowserPath()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ApplicationSettings.appSettings().LogEvents)
|
||||
{
|
||||
CrossProductLogging.WriteEventLogFile("Begin GetDefaultBrowserPath");
|
||||
}
|
||||
|
||||
string key = @"htmlfile\shell\open\command";
|
||||
RegistryKey registryKey =
|
||||
Registry.ClassesRoot.OpenSubKey(key, false);
|
||||
// get default browser path
|
||||
if (ApplicationSettings.appSettings().LogEvents)
|
||||
{
|
||||
CrossProductLogging.WriteEventLogFile("End GetDefaultBrowserPath");
|
||||
}
|
||||
return ((string)registryKey.GetValue(null, null)).Split('"')[1];
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
238
@integrate/SysTray.cs
Normal file
238
@integrate/SysTray.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using WatchdogLib.Thread;
|
||||
using System.Timers;
|
||||
|
||||
namespace WatchdogLib.WinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper Class around .Net NotifyIcon, to make it easier to work with an System Tray Icon.
|
||||
/// Instantiate the object and set ContextMenu or ContextMenuStrip in order to have a right click menu.
|
||||
/// Subscripe to the MouseLeftClick, and MouseLeftDoubleClick event to get accurate events to handle,
|
||||
/// Call Show()/Hide() to show/hide the System Tray Icon, respectively.
|
||||
/// </summary>
|
||||
public class SysTray
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
public NotifyIcon trayNotify { get; private set; }
|
||||
public Icon Icon { get { return trayNotify.Icon; } set { trayNotify.Icon = value; } }
|
||||
public ContextMenu trayMenu { get { return trayNotify.ContextMenu; } set { trayNotify.ContextMenu = value; } }
|
||||
public ContextMenuStrip trayMenuStrip { get { return trayNotify.ContextMenuStrip; } set { trayNotify.ContextMenuStrip = value; } }
|
||||
public string toolTip { get { return trayNotify.Text; } set { trayNotify.Text = value; } }
|
||||
public bool Visible { get { return trayNotify.Visible; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Events
|
||||
|
||||
public delegate void SingleLeftMouseClick(MouseEventArgs e);
|
||||
/// <summary>
|
||||
/// Subscribe to get the Left Mouse Single Click Event
|
||||
/// </summary>
|
||||
public event SingleLeftMouseClick LeftMouseClick;
|
||||
|
||||
public delegate void DoubleLeftMouseClick(MouseEventArgs e);
|
||||
/// <summary>
|
||||
/// Subscribe to get the Left Mouse Double Click Event
|
||||
/// </summary>
|
||||
public event DoubleLeftMouseClick LeftMouseDoubleClick;
|
||||
|
||||
public delegate void RightMouseClick(MouseEventArgs e);
|
||||
/// <summary>
|
||||
/// Subscribe to get any Right Mouse Fired Event, use to redo context menu, if needed
|
||||
/// </summary>
|
||||
public event RightMouseClick RightMouseFired;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
|
||||
private TTimer SingleClickDetectTimer = null;
|
||||
private TimeSpan _LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
private const int _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT = 500;
|
||||
private const int _N_SECONDS_TOIGNORE_NEXT_SIGNLEMOUSE_CLICKEVENT = 2; // to avoid tripple clicks, etc... (only sends one double click)
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if enough time since _LastFiredEvent has passed
|
||||
/// </summary>
|
||||
private bool EnoughTimeSinceLastEventHasElapsed
|
||||
{
|
||||
get
|
||||
{
|
||||
// 1 second is 10 Million ticks, one Milisecond is 10K
|
||||
return (DateTime.Now.Ticks - _LastFiredEvent.Ticks) >= (_N_SECONDS_TOIGNORE_NEXT_SIGNLEMOUSE_CLICKEVENT * 1000 * 10000);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Construct a System Tray Icon (use public properties like ContextMenu,Icon,toolTip to customize further)
|
||||
/// </summary>
|
||||
/// <param name="toolTip">pass in an initial ToolTip to display, defaults to ""</param>
|
||||
/// <param name="icon">if null, defaults to systemIcons.Application</param>
|
||||
//public SysTray(string toolTip = "", Icon icon = null)
|
||||
public SysTray(string toolTip, Icon icon)
|
||||
{
|
||||
// Create internal objects
|
||||
this.trayNotify = new NotifyIcon();
|
||||
this.SingleClickDetectTimer = new TTimer(new ElapsedEventHandler(RealSingleClickDetectTimer_ElapsedEventHandler), _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT, false, true);
|
||||
|
||||
// Add Single / Double-Click Event Handlers
|
||||
trayNotify.Click += new EventHandler(trayNotify_Click);
|
||||
trayNotify.DoubleClick += new EventHandler(trayNotify_DoubleClick);
|
||||
trayNotify.MouseDown += new MouseEventHandler(trayNotify_MouseDown);
|
||||
|
||||
// Set ToolTip
|
||||
if (!String.IsNullOrEmpty(toolTip))
|
||||
this.toolTip = toolTip;
|
||||
|
||||
// Set Icon
|
||||
if (icon == null)
|
||||
this.Icon = new Icon(SystemIcons.Application, 40, 40);
|
||||
else
|
||||
this.Icon = icon;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Click Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Called by NotifyIcon DoubleClick Event, We filter for only the left mouse double-click,
|
||||
/// event and fire event when neccessary
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void trayNotify_DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
MouseEventArgs args = (MouseEventArgs)e;
|
||||
if (args.Button == MouseButtons.Left)
|
||||
{
|
||||
SingleClickDetectTimer.Stop();
|
||||
if (LeftMouseDoubleClick != null && EnoughTimeSinceLastEventHasElapsed)
|
||||
{
|
||||
_LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
LeftMouseDoubleClick(new MouseEventArgs(MouseButtons.Left, 2, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
// Called by NotifyIcon Click Event, We filter for only the left mouse click,
|
||||
/// event and fire event when neccessary
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void trayNotify_Click(object sender, EventArgs e)
|
||||
{
|
||||
MouseEventArgs args = (MouseEventArgs) e;
|
||||
if (args.Button == MouseButtons.Left && EnoughTimeSinceLastEventHasElapsed)
|
||||
SingleClickDetectTimer.Start(); // Start Single Click Detect Timer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In order to accurately re-do a context menu, we handle MouseDown for the
|
||||
/// Right-Mouse click. Mouse Down comes in before the click event, which gives
|
||||
/// the caller an opportunity to handle/recreate the context menu dynamically, if needed
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void trayNotify_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
MouseEventArgs args = (MouseEventArgs)e;
|
||||
if (args.Button == MouseButtons.Right && (RightMouseFired != null))
|
||||
RightMouseFired(args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to detect ONLY Single Clicks, since a single-click and then a double-click fires,
|
||||
/// we want to ignore the first click,and first see if a double-click comes in, if so, ignore
|
||||
/// the single click, otherwise send it. (this is done by trayNotify_Click & transNotify_DoubleClick)
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void RealSingleClickDetectTimer_ElapsedEventHandler(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
SingleClickDetectTimer.Stop();
|
||||
if (LeftMouseClick != null)
|
||||
{
|
||||
_LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
LeftMouseClick(new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Show N' Hide
|
||||
|
||||
/// <summary>
|
||||
/// Show the System Tray Icon
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
trayNotify.Visible = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hide the System Tray Icon
|
||||
/// </summary>
|
||||
public void Hide()
|
||||
{
|
||||
trayNotify.Visible = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public ShowBallon
|
||||
|
||||
/// <summary>
|
||||
/// Pops up a Ballon over the System Tray Icon
|
||||
/// </summary>
|
||||
/// <param name="nTimeoutInSeconds">Specify the Timeout in Seconds</param>
|
||||
//public void ShowBallon_Default(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds = 10)
|
||||
public void ShowBallon_Default(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds)
|
||||
{
|
||||
trayNotify.ShowBalloonTip((nTimeoutInSeconds * 1000), BallonTipTitle, BallonTipText, ToolTipIcon.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pops up a Error Ballon over the System Tray Icon
|
||||
/// </summary>
|
||||
/// <param name="nTimeoutInSeconds">Specify the Timeout in Seconds</param>
|
||||
//public void ShowBallon_Error(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds = 10)
|
||||
public void ShowBallon_Error(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds)
|
||||
{
|
||||
trayNotify.ShowBalloonTip((nTimeoutInSeconds * 1000), BallonTipTitle, BallonTipText, ToolTipIcon.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pops up a Warning Ballon over the System Tray Icon
|
||||
/// </summary>
|
||||
/// <param name="nTimeoutInSeconds">Specify the Timeout in Seconds</param>
|
||||
//public void ShowBallon_Warning(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds = 10)
|
||||
public void ShowBallon_Warning(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds)
|
||||
{
|
||||
trayNotify.ShowBalloonTip((nTimeoutInSeconds * 1000), BallonTipTitle, BallonTipText, ToolTipIcon.Warning);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pops up a Info Ballon over the System Tray Icon
|
||||
/// </summary>
|
||||
/// <param name="nTimeoutInSeconds">Specify the Timeout in Seconds</param>
|
||||
//public void ShowBallon_Info(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds = 10)
|
||||
public void ShowBallon_Info(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds)
|
||||
{
|
||||
trayNotify.ShowBalloonTip((nTimeoutInSeconds * 1000), BallonTipTitle, BallonTipText, ToolTipIcon.Info);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
140
@integrate/TTimer.cs
Normal file
140
@integrate/TTimer.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
using System.Windows.Threading;
|
||||
using WinThread = System.Threading;
|
||||
|
||||
namespace WatchdogLib.Thread
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper class around Timer Objects
|
||||
/// </summary>
|
||||
public class TTimer : IDisposable
|
||||
{
|
||||
// private Members
|
||||
private Timer _Timer = new Timer();
|
||||
private bool _disposed = false;
|
||||
private Dispatcher _Dispatcher = null;
|
||||
private ElapsedEventHandler _DispatchedElapsedEvent = null;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Multi-threaded System.Timer
|
||||
/// </summary>
|
||||
/// <param name="ElapsedHandler">Event Handler for Timer</param>
|
||||
/// <param name="IntervalMiliseconds">Interval in Miliseconds</param>
|
||||
/// <param name="StartEnabled">True to start the timer upon creation, false otherwise</param>
|
||||
/// <returns>A Timer Object, which should be Disposed by Caller</returns>
|
||||
//public TTimer(ElapsedEventHandler ElapsedHandler, int IntervalMiliseconds = 1000, bool StartEnabled = false, bool bUseDispatcher = true)
|
||||
public TTimer(ElapsedEventHandler ElapsedHandler, int IntervalMiliseconds, bool StartEnabled, bool bUseDispatcher)
|
||||
{
|
||||
if (ElapsedHandler != null)
|
||||
{
|
||||
_Timer = new System.Timers.Timer();
|
||||
|
||||
// The Primary Dispatcher thread is the thread that called us
|
||||
if (bUseDispatcher)
|
||||
{
|
||||
_Dispatcher = Dispatcher.CurrentDispatcher;
|
||||
_DispatchedElapsedEvent = ElapsedHandler;
|
||||
_Timer.Elapsed += new ElapsedEventHandler(_Timer_Elapsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
_Timer.Elapsed += ElapsedHandler;
|
||||
}
|
||||
|
||||
// Set the Interval / start
|
||||
_Timer.Interval = IntervalMiliseconds;
|
||||
_Timer.Enabled = StartEnabled;
|
||||
if (StartEnabled)
|
||||
_Timer.Start();
|
||||
|
||||
// Keep the timer alive
|
||||
GC.KeepAlive(_Timer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For Dispatching the Event to the Primary Dispatcher Thread
|
||||
/// </summary>
|
||||
void _Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
object[] param_s = new object[] { sender, e };
|
||||
_Dispatcher.Invoke((ElapsedEventHandler)_DispatchedElapsedEvent, param_s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually Start the Timer
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
Stop(); // First Stop(), an existing Timer
|
||||
_Timer.Enabled = true;
|
||||
_Timer.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually Start the Timer at a new Interval
|
||||
/// </summary>
|
||||
/// <param name="IntervalMiliseconds">Interval in Miliseconds</param>
|
||||
public void Start(uint IntervalMiliseconds)
|
||||
{
|
||||
Stop(); // First Stop(), an existing Timer
|
||||
_Timer.Interval = IntervalMiliseconds;
|
||||
_Timer.Enabled = true;
|
||||
_Timer.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually Start the Timer at a new Interval
|
||||
/// </summary>
|
||||
/// <param name="tsInterval">Interval as a TimeSpan</param>
|
||||
public void Start(TimeSpan tsInterval)
|
||||
{
|
||||
Stop(); // First Stop(), an existing Timer
|
||||
_Timer.Interval = tsInterval.TotalMilliseconds;
|
||||
_Timer.Enabled = true;
|
||||
_Timer.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually Stop the Timer
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
_Timer.Enabled = false;
|
||||
_Timer.Stop();
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// Use SupressFinalize in case a subclass
|
||||
// of this type implements a finalizer
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_Timer != null)
|
||||
_Timer.Dispose();
|
||||
}
|
||||
|
||||
// Indicate that the instance has been disposed.
|
||||
_Timer = null;
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
654
@integrate/Trinet.Core.IO.Ntfs/AlternateDataStreamInfo.cs
Normal file
654
@integrate/Trinet.Core.IO.Ntfs/AlternateDataStreamInfo.cs
Normal file
@@ -0,0 +1,654 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace Trinet.Core.IO.Ntfs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the details of an alternative data stream.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{FullPath}")]
|
||||
public sealed class AlternateDataStreamInfo : IEquatable<AlternateDataStreamInfo>
|
||||
{
|
||||
#region Private Data
|
||||
|
||||
private readonly string _fullPath;
|
||||
private readonly string _filePath;
|
||||
private readonly string _streamName;
|
||||
private readonly FileStreamType _streamType;
|
||||
private readonly FileStreamAttributes _attributes;
|
||||
private readonly long _size;
|
||||
private readonly bool _exists;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AlternateDataStreamInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="filePath">
|
||||
/// The full path of the file.
|
||||
/// This argument must not be <see langword="null"/>.
|
||||
/// </param>
|
||||
/// <param name="info">
|
||||
/// The <see cref="SafeNativeMethods.Win32StreamInfo"/> containing the stream information.
|
||||
/// </param>
|
||||
internal AlternateDataStreamInfo(string filePath, SafeNativeMethods.Win32StreamInfo info)
|
||||
{
|
||||
_filePath = filePath;
|
||||
_streamName = info.StreamName;
|
||||
_streamType = info.StreamType;
|
||||
_attributes = info.StreamAttributes;
|
||||
_size = info.StreamSize;
|
||||
_exists = true;
|
||||
|
||||
_fullPath = SafeNativeMethods.BuildStreamPath(_filePath, _streamName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AlternateDataStreamInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="filePath">
|
||||
/// The full path of the file.
|
||||
/// This argument must not be <see langword="null"/>.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream
|
||||
/// This argument must not be <see langword="null"/>.
|
||||
/// </param>
|
||||
/// <param name="fullPath">
|
||||
/// The full path of the stream.
|
||||
/// If this argument is <see langword="null"/>, it will be generated from the
|
||||
/// <paramref name="filePath"/> and <paramref name="streamName"/> arguments.
|
||||
/// </param>
|
||||
/// <param name="exists">
|
||||
/// <see langword="true"/> if the stream exists;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </param>
|
||||
internal AlternateDataStreamInfo(string filePath, string streamName, string fullPath, bool exists)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fullPath)) fullPath = SafeNativeMethods.BuildStreamPath(filePath, streamName);
|
||||
_streamType = FileStreamType.AlternateDataStream;
|
||||
|
||||
_filePath = filePath;
|
||||
_streamName = streamName;
|
||||
_fullPath = fullPath;
|
||||
_exists = exists;
|
||||
|
||||
if (_exists)
|
||||
{
|
||||
_size = SafeNativeMethods.GetFileSize(_fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full path of this stream.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The full path of this stream.
|
||||
/// </value>
|
||||
public string FullPath
|
||||
{
|
||||
get { return _fullPath; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full path of the file which contains the stream.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The full file-system path of the file which contains the stream.
|
||||
/// </value>
|
||||
public string FilePath
|
||||
{
|
||||
get { return _filePath; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the stream.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the stream.
|
||||
/// </value>
|
||||
public string Name
|
||||
{
|
||||
get { return _streamName; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a flag indicating whether the specified stream exists.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> if the stream exists;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </value>
|
||||
public bool Exists
|
||||
{
|
||||
get { return _exists; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the size of the stream, in bytes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of the stream, in bytes.
|
||||
/// </value>
|
||||
public long Size
|
||||
{
|
||||
get { return _size; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the type of data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// One of the <see cref="FileStreamType"/> values.
|
||||
/// </value>
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
public FileStreamType StreamType
|
||||
{
|
||||
get { return _streamType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns attributes of the data stream.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A combination of <see cref="FileStreamAttributes"/> values.
|
||||
/// </value>
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
public FileStreamAttributes Attributes
|
||||
{
|
||||
get { return _attributes; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
#region -IEquatable
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="String"/> that represents the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="String"/> that represents the current instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.FullPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serves as a hash function for a particular type.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A hash code for the current <see cref="Object"/>.
|
||||
/// </returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var comparer = StringComparer.OrdinalIgnoreCase;
|
||||
return comparer.GetHashCode(_filePath ?? string.Empty)
|
||||
^ comparer.GetHashCode(_streamName ?? string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the current object is equal to another object of the same type.
|
||||
/// </summary>
|
||||
/// <param name="obj">
|
||||
/// An object to compare with this object.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the current object is equal to the <paramref name="obj"/> parameter;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (object.ReferenceEquals(null, obj)) return false;
|
||||
if (object.ReferenceEquals(this, obj)) return true;
|
||||
|
||||
AlternateDataStreamInfo other = obj as AlternateDataStreamInfo;
|
||||
if (!object.ReferenceEquals(null, other)) return this.Equals(other);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether
|
||||
/// this instance is equal to another instance.
|
||||
/// </summary>
|
||||
/// <param name="other">
|
||||
/// The instance to compare to.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the current object is equal to the <paramref name="other"/> parameter;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
public bool Equals(AlternateDataStreamInfo other)
|
||||
{
|
||||
if (object.ReferenceEquals(null, other)) return false;
|
||||
if (object.ReferenceEquals(this, other)) return true;
|
||||
|
||||
var comparer = StringComparer.OrdinalIgnoreCase;
|
||||
return comparer.Equals(this._filePath ?? string.Empty, other._filePath ?? string.Empty)
|
||||
&& comparer.Equals(this._streamName ?? string.Empty, other._streamName ?? string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The equality operator.
|
||||
/// </summary>
|
||||
/// <param name="first">
|
||||
/// The first object.
|
||||
/// </param>
|
||||
/// <param name="second">
|
||||
/// The second object.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the two objects are equal;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
public static bool operator ==(AlternateDataStreamInfo first, AlternateDataStreamInfo second)
|
||||
{
|
||||
if (object.ReferenceEquals(first, second)) return true;
|
||||
if (object.ReferenceEquals(null, first)) return false;
|
||||
if (object.ReferenceEquals(null, second)) return false;
|
||||
return first.Equals(second);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The inequality operator.
|
||||
/// </summary>
|
||||
/// <param name="first">
|
||||
/// The first object.
|
||||
/// </param>
|
||||
/// <param name="second">
|
||||
/// The second object.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the two objects are not equal;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
public static bool operator !=(AlternateDataStreamInfo first, AlternateDataStreamInfo second)
|
||||
{
|
||||
if (object.ReferenceEquals(first, second)) return false;
|
||||
if (object.ReferenceEquals(null, first)) return true;
|
||||
if (object.ReferenceEquals(null, second)) return true;
|
||||
return !first.Equals(second);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region -Delete
|
||||
|
||||
/// <summary>
|
||||
/// Deletes this stream from the parent file.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the stream was deleted;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
public bool Delete()
|
||||
{
|
||||
const FileIOPermissionAccess permAccess = FileIOPermissionAccess.Write;
|
||||
new FileIOPermission(permAccess, _filePath).Demand();
|
||||
return SafeNativeMethods.SafeDeleteFile(this.FullPath);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region -Open
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the access to demand.
|
||||
/// </summary>
|
||||
/// <param name="mode">
|
||||
/// The <see cref="FileMode"/>.
|
||||
/// </param>
|
||||
/// <param name="access">
|
||||
/// The <see cref="FileAccess"/>.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="FileIOPermissionAccess"/>.
|
||||
/// </returns>
|
||||
private static FileIOPermissionAccess CalculateAccess(FileMode mode, FileAccess access)
|
||||
{
|
||||
FileIOPermissionAccess permAccess = FileIOPermissionAccess.NoAccess;
|
||||
switch (mode)
|
||||
{
|
||||
case FileMode.Append:
|
||||
permAccess = FileIOPermissionAccess.Append;
|
||||
break;
|
||||
|
||||
case FileMode.Create:
|
||||
case FileMode.CreateNew:
|
||||
case FileMode.OpenOrCreate:
|
||||
case FileMode.Truncate:
|
||||
permAccess = FileIOPermissionAccess.Write;
|
||||
break;
|
||||
|
||||
case FileMode.Open:
|
||||
permAccess = FileIOPermissionAccess.Read;
|
||||
break;
|
||||
}
|
||||
switch (access)
|
||||
{
|
||||
case FileAccess.ReadWrite:
|
||||
permAccess |= FileIOPermissionAccess.Write;
|
||||
permAccess |= FileIOPermissionAccess.Read;
|
||||
break;
|
||||
|
||||
case FileAccess.Write:
|
||||
permAccess |= FileIOPermissionAccess.Write;
|
||||
break;
|
||||
|
||||
case FileAccess.Read:
|
||||
permAccess |= FileIOPermissionAccess.Read;
|
||||
break;
|
||||
}
|
||||
|
||||
return permAccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens this alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="mode">
|
||||
/// A <see cref="FileMode"/> value that specifies whether a stream is created if one does not exist,
|
||||
/// and determines whether the contents of existing streams are retained or overwritten.
|
||||
/// </param>
|
||||
/// <param name="access">
|
||||
/// A <see cref="FileAccess"/> value that specifies the operations that can be performed on the stream.
|
||||
/// </param>
|
||||
/// <param name="share">
|
||||
/// A <see cref="FileShare"/> value specifying the type of access other threads have to the file.
|
||||
/// </param>
|
||||
/// <param name="bufferSize">
|
||||
/// The size of the buffer to use.
|
||||
/// </param>
|
||||
/// <param name="useAsync">
|
||||
/// <see langword="true"/> to enable async-IO;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="FileStream"/> for this alternate data stream.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="bufferSize"/> is less than or equal to zero.
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
/// <exception cref="Win32Exception">
|
||||
/// There was an error opening the stream.
|
||||
/// </exception>
|
||||
public FileStream Open(FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync)
|
||||
{
|
||||
if (0 >= bufferSize) throw new ArgumentOutOfRangeException("bufferSize", bufferSize, null);
|
||||
|
||||
FileIOPermissionAccess permAccess = CalculateAccess(mode, access);
|
||||
new FileIOPermission(permAccess, _filePath).Demand();
|
||||
|
||||
SafeNativeMethods.NativeFileFlags flags = useAsync ? SafeNativeMethods.NativeFileFlags.Overlapped : 0;
|
||||
var handle = SafeNativeMethods.SafeCreateFile(this.FullPath, access.ToNative(), share, IntPtr.Zero, mode, flags, IntPtr.Zero);
|
||||
if (handle.IsInvalid) SafeNativeMethods.ThrowLastIOError(this.FullPath);
|
||||
return new FileStream(handle, access, bufferSize, useAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens this alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="mode">
|
||||
/// A <see cref="FileMode"/> value that specifies whether a stream is created if one does not exist,
|
||||
/// and determines whether the contents of existing streams are retained or overwritten.
|
||||
/// </param>
|
||||
/// <param name="access">
|
||||
/// A <see cref="FileAccess"/> value that specifies the operations that can be performed on the stream.
|
||||
/// </param>
|
||||
/// <param name="share">
|
||||
/// A <see cref="FileShare"/> value specifying the type of access other threads have to the file.
|
||||
/// </param>
|
||||
/// <param name="bufferSize">
|
||||
/// The size of the buffer to use.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="FileStream"/> for this alternate data stream.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="bufferSize"/> is less than or equal to zero.
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
/// <exception cref="Win32Exception">
|
||||
/// There was an error opening the stream.
|
||||
/// </exception>
|
||||
public FileStream Open(FileMode mode, FileAccess access, FileShare share, int bufferSize)
|
||||
{
|
||||
return this.Open(mode, access, share, bufferSize, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens this alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="mode">
|
||||
/// A <see cref="FileMode"/> value that specifies whether a stream is created if one does not exist,
|
||||
/// and determines whether the contents of existing streams are retained or overwritten.
|
||||
/// </param>
|
||||
/// <param name="access">
|
||||
/// A <see cref="FileAccess"/> value that specifies the operations that can be performed on the stream.
|
||||
/// </param>
|
||||
/// <param name="share">
|
||||
/// A <see cref="FileShare"/> value specifying the type of access other threads have to the file.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="FileStream"/> for this alternate data stream.
|
||||
/// </returns>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
/// <exception cref="Win32Exception">
|
||||
/// There was an error opening the stream.
|
||||
/// </exception>
|
||||
public FileStream Open(FileMode mode, FileAccess access, FileShare share)
|
||||
{
|
||||
return this.Open(mode, access, share, SafeNativeMethods.DefaultBufferSize, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens this alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="mode">
|
||||
/// A <see cref="FileMode"/> value that specifies whether a stream is created if one does not exist,
|
||||
/// and determines whether the contents of existing streams are retained or overwritten.
|
||||
/// </param>
|
||||
/// <param name="access">
|
||||
/// A <see cref="FileAccess"/> value that specifies the operations that can be performed on the stream.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="FileStream"/> for this alternate data stream.
|
||||
/// </returns>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
/// <exception cref="Win32Exception">
|
||||
/// There was an error opening the stream.
|
||||
/// </exception>
|
||||
public FileStream Open(FileMode mode, FileAccess access)
|
||||
{
|
||||
return this.Open(mode, access, FileShare.None, SafeNativeMethods.DefaultBufferSize, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens this alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="mode">
|
||||
/// A <see cref="FileMode"/> value that specifies whether a stream is created if one does not exist,
|
||||
/// and determines whether the contents of existing streams are retained or overwritten.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="FileStream"/> for this alternate data stream.
|
||||
/// </returns>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
/// <exception cref="Win32Exception">
|
||||
/// There was an error opening the stream.
|
||||
/// </exception>
|
||||
public FileStream Open(FileMode mode)
|
||||
{
|
||||
FileAccess access = (FileMode.Append == mode) ? FileAccess.Write : FileAccess.ReadWrite;
|
||||
return this.Open(mode, access, FileShare.None, SafeNativeMethods.DefaultBufferSize, false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region -OpenRead / OpenWrite / OpenText
|
||||
|
||||
/// <summary>
|
||||
/// Opens this stream for reading.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A read-only <see cref="FileStream"/> for this stream.
|
||||
/// </returns>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
/// <exception cref="Win32Exception">
|
||||
/// There was an error opening the stream.
|
||||
/// </exception>
|
||||
public FileStream OpenRead()
|
||||
{
|
||||
return this.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens this stream for writing.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A write-only <see cref="FileStream"/> for this stream.
|
||||
/// </returns>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
/// <exception cref="Win32Exception">
|
||||
/// There was an error opening the stream.
|
||||
/// </exception>
|
||||
public FileStream OpenWrite()
|
||||
{
|
||||
return this.Open(FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens this stream as a text file.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="StreamReader"/> which can be used to read the contents of this stream.
|
||||
/// </returns>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The path of the stream is invalid.
|
||||
/// </exception>
|
||||
/// <exception cref="Win32Exception">
|
||||
/// There was an error opening the stream.
|
||||
/// </exception>
|
||||
public StreamReader OpenText()
|
||||
{
|
||||
Stream fileStream = this.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
return new StreamReader(fileStream);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
32
@integrate/Trinet.Core.IO.Ntfs/FileStreamAttributes.cs
Normal file
32
@integrate/Trinet.Core.IO.Ntfs/FileStreamAttributes.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
namespace Trinet.Core.IO.Ntfs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the attributes of a file stream.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum FileStreamAttributes
|
||||
{
|
||||
/// <summary>
|
||||
/// No attributes.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// Set if the stream contains data that is modified when read.
|
||||
/// </summary>
|
||||
ModifiedWhenRead = 1,
|
||||
/// <summary>
|
||||
/// Set if the stream contains security data.
|
||||
/// </summary>
|
||||
ContainsSecurity = 2,
|
||||
/// <summary>
|
||||
/// Set if the stream contains properties.
|
||||
/// </summary>
|
||||
ContainsProperties = 4,
|
||||
/// <summary>
|
||||
/// Set if the stream is sparse.
|
||||
/// </summary>
|
||||
Sparse = 8,
|
||||
}
|
||||
}
|
||||
56
@integrate/Trinet.Core.IO.Ntfs/FileStreamType.cs
Normal file
56
@integrate/Trinet.Core.IO.Ntfs/FileStreamType.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
|
||||
namespace Trinet.Core.IO.Ntfs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the type of data in a stream.
|
||||
/// </summary>
|
||||
public enum FileStreamType
|
||||
{
|
||||
/// <summary>
|
||||
/// Unknown stream type.
|
||||
/// </summary>
|
||||
Unknown = 0,
|
||||
/// <summary>
|
||||
/// Standard data.
|
||||
/// </summary>
|
||||
Data = 1,
|
||||
/// <summary>
|
||||
/// Extended attribute data.
|
||||
/// </summary>
|
||||
ExtendedAttributes = 2,
|
||||
/// <summary>
|
||||
/// Security data.
|
||||
/// </summary>
|
||||
SecurityData = 3,
|
||||
/// <summary>
|
||||
/// Alternate data stream.
|
||||
/// </summary>
|
||||
AlternateDataStream = 4,
|
||||
/// <summary>
|
||||
/// Hard link information.
|
||||
/// </summary>
|
||||
Link = 5,
|
||||
/// <summary>
|
||||
/// Property data.
|
||||
/// </summary>
|
||||
PropertyData = 6,
|
||||
/// <summary>
|
||||
/// Object identifiers.
|
||||
/// </summary>
|
||||
ObjectId = 7,
|
||||
/// <summary>
|
||||
/// Reparse points.
|
||||
/// </summary>
|
||||
ReparseData = 8,
|
||||
/// <summary>
|
||||
/// Sparse file.
|
||||
/// </summary>
|
||||
SparseBlock = 9,
|
||||
/// <summary>
|
||||
/// Transactional data.
|
||||
/// (Undocumented - BACKUP_TXFS_DATA)
|
||||
/// </summary>
|
||||
TransactionData = 10,
|
||||
}
|
||||
}
|
||||
452
@integrate/Trinet.Core.IO.Ntfs/FileSystem.cs
Normal file
452
@integrate/Trinet.Core.IO.Ntfs/FileSystem.cs
Normal file
@@ -0,0 +1,452 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace Trinet.Core.IO.Ntfs
|
||||
{
|
||||
using Resources = Properties.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// File-system utilities.
|
||||
/// </summary>
|
||||
public static class FileSystem
|
||||
{
|
||||
#region Create FileSystemInfo
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="FileSystemInfo"/> for the specified path.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// The path of the file or directory.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="FileSystemInfo"/> representing the file or directory.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path"/> is <see langword="null"/> or empty.
|
||||
/// </exception>
|
||||
private static FileSystemInfo CreateInfo(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
|
||||
|
||||
path = Path.GetFullPath(path);
|
||||
if (!File.Exists(path) && Directory.Exists(path)) return new DirectoryInfo(path);
|
||||
return new FileInfo(path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region List Streams
|
||||
|
||||
/// <summary>
|
||||
/// <span style="font-weight:bold;color:#a00;">(Extension Method)</span><br />
|
||||
/// Returns a read-only list of alternate data streams for the specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// The <see cref="FileSystemInfo"/> to inspect.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A read-only list of <see cref="AlternateDataStreamInfo"/> objects
|
||||
/// representing the alternate data streams for the specified file, if any.
|
||||
/// If no streams are found, returns an empty list.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="FileNotFoundException">
|
||||
/// The specified <paramref name="file"/> does not exist.
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
public static IList<AlternateDataStreamInfo> ListAlternateDataStreams(this FileSystemInfo file)
|
||||
{
|
||||
if (null == file) throw new ArgumentNullException("file");
|
||||
if (!file.Exists) throw new FileNotFoundException(null, file.FullName);
|
||||
|
||||
string path = file.FullName;
|
||||
new FileIOPermission(FileIOPermissionAccess.Read, path).Demand();
|
||||
|
||||
return SafeNativeMethods.ListStreams(path)
|
||||
.Select(s => new AlternateDataStreamInfo(path, s))
|
||||
.ToList().AsReadOnly();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a read-only list of alternate data streams for the specified file.
|
||||
/// </summary>
|
||||
/// <param name="filePath">
|
||||
/// The full path of the file to inspect.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A read-only list of <see cref="AlternateDataStreamInfo"/> objects
|
||||
/// representing the alternate data streams for the specified file, if any.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="filePath"/> is <see langword="null"/> or an empty string.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="filePath"/> is not a valid file path.
|
||||
/// </exception>
|
||||
/// <exception cref="FileNotFoundException">
|
||||
/// The specified <paramref name="filePath"/> does not exist.
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
public static IList<AlternateDataStreamInfo> ListAlternateDataStreams(string filePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath");
|
||||
return CreateInfo(filePath).ListAlternateDataStreams();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Exists
|
||||
|
||||
/// <summary>
|
||||
/// <span style="font-weight:bold;color:#a00;">(Extension Method)</span><br />
|
||||
/// Returns a flag indicating whether the specified alternate data stream exists.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// The <see cref="FileInfo"/> to inspect.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream to find.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the specified stream exists;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="streamName"/> contains invalid characters.
|
||||
/// </exception>
|
||||
public static bool AlternateDataStreamExists(this FileSystemInfo file, string streamName)
|
||||
{
|
||||
if (null == file) throw new ArgumentNullException("file");
|
||||
SafeNativeMethods.ValidateStreamName(streamName);
|
||||
|
||||
string path = SafeNativeMethods.BuildStreamPath(file.FullName, streamName);
|
||||
return -1 != SafeNativeMethods.SafeGetFileAttributes(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a flag indicating whether the specified alternate data stream exists.
|
||||
/// </summary>
|
||||
/// <param name="filePath">
|
||||
/// The path of the file to inspect.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream to find.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the specified stream exists;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="filePath"/> is <see langword="null"/> or an empty string.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <para><paramref name="filePath"/> is not a valid file path.</para>
|
||||
/// <para>-or-</para>
|
||||
/// <para><paramref name="streamName"/> contains invalid characters.</para>
|
||||
/// </exception>
|
||||
public static bool AlternateDataStreamExists(string filePath, string streamName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath");
|
||||
return CreateInfo(filePath).AlternateDataStreamExists(streamName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Open Stream
|
||||
|
||||
/// <summary>
|
||||
/// <span style="font-weight:bold;color:#a00;">(Extension Method)</span><br />
|
||||
/// Opens an alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// The <see cref="FileInfo"/> which contains the stream.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream to open.
|
||||
/// </param>
|
||||
/// <param name="mode">
|
||||
/// One of the <see cref="FileMode"/> values, indicating how the stream is to be opened.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An <see cref="AlternateDataStreamInfo"/> representing the stream.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="FileNotFoundException">
|
||||
/// The specified <paramref name="file"/> was not found.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="streamName"/> contains invalid characters.
|
||||
/// </exception>
|
||||
/// <exception cref="NotSupportedException">
|
||||
/// <paramref name="mode"/> is either <see cref="FileMode.Truncate"/> or <see cref="FileMode.Append"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// <para><paramref name="mode"/> is <see cref="FileMode.Open"/>, and the stream doesn't exist.</para>
|
||||
/// <para>-or-</para>
|
||||
/// <para><paramref name="mode"/> is <see cref="FileMode.CreateNew"/>, and the stream already exists.</para>
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
public static AlternateDataStreamInfo GetAlternateDataStream(this FileSystemInfo file, string streamName, FileMode mode)
|
||||
{
|
||||
if (null == file) throw new ArgumentNullException("file");
|
||||
if (!file.Exists) throw new FileNotFoundException(null, file.FullName);
|
||||
SafeNativeMethods.ValidateStreamName(streamName);
|
||||
|
||||
if (FileMode.Truncate == mode || FileMode.Append == mode)
|
||||
{
|
||||
throw new NotSupportedException(string.Format(Resources.Culture,
|
||||
Resources.Error_InvalidMode, mode));
|
||||
}
|
||||
|
||||
FileIOPermissionAccess permAccess = (FileMode.Open == mode) ? FileIOPermissionAccess.Read : FileIOPermissionAccess.Read | FileIOPermissionAccess.Write;
|
||||
new FileIOPermission(permAccess, file.FullName).Demand();
|
||||
|
||||
string path = SafeNativeMethods.BuildStreamPath(file.FullName, streamName);
|
||||
bool exists = -1 != SafeNativeMethods.SafeGetFileAttributes(path);
|
||||
|
||||
if (!exists && FileMode.Open == mode)
|
||||
{
|
||||
throw new IOException(string.Format(Resources.Culture,
|
||||
Resources.Error_StreamNotFound, streamName, file.Name));
|
||||
}
|
||||
if (exists && FileMode.CreateNew == mode)
|
||||
{
|
||||
throw new IOException(string.Format(Resources.Culture,
|
||||
Resources.Error_StreamExists, streamName, file.Name));
|
||||
}
|
||||
|
||||
return new AlternateDataStreamInfo(file.FullName, streamName, path, exists);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <span style="font-weight:bold;color:#a00;">(Extension Method)</span><br />
|
||||
/// Opens an alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// The <see cref="FileInfo"/> which contains the stream.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream to open.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An <see cref="AlternateDataStreamInfo"/> representing the stream.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="FileNotFoundException">
|
||||
/// The specified <paramref name="file"/> was not found.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="streamName"/> contains invalid characters.
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
public static AlternateDataStreamInfo GetAlternateDataStream(this FileSystemInfo file, string streamName)
|
||||
{
|
||||
return file.GetAlternateDataStream(streamName, FileMode.OpenOrCreate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens an alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="filePath">
|
||||
/// The path of the file which contains the stream.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream to open.
|
||||
/// </param>
|
||||
/// <param name="mode">
|
||||
/// One of the <see cref="FileMode"/> values, indicating how the stream is to be opened.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An <see cref="AlternateDataStreamInfo"/> representing the stream.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="filePath"/> is <see langword="null"/> or an empty string.
|
||||
/// </exception>
|
||||
/// <exception cref="FileNotFoundException">
|
||||
/// The specified <paramref name="filePath"/> was not found.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <para><paramref name="filePath"/> is not a valid file path.</para>
|
||||
/// <para>-or-</para>
|
||||
/// <para><paramref name="streamName"/> contains invalid characters.</para>
|
||||
/// </exception>
|
||||
/// <exception cref="NotSupportedException">
|
||||
/// <paramref name="mode"/> is either <see cref="FileMode.Truncate"/> or <see cref="FileMode.Append"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// <para><paramref name="mode"/> is <see cref="FileMode.Open"/>, and the stream doesn't exist.</para>
|
||||
/// <para>-or-</para>
|
||||
/// <para><paramref name="mode"/> is <see cref="FileMode.CreateNew"/>, and the stream already exists.</para>
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
public static AlternateDataStreamInfo GetAlternateDataStream(string filePath, string streamName, FileMode mode)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath");
|
||||
return CreateInfo(filePath).GetAlternateDataStream(streamName, mode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens an alternate data stream.
|
||||
/// </summary>
|
||||
/// <param name="filePath">
|
||||
/// The path of the file which contains the stream.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream to open.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An <see cref="AlternateDataStreamInfo"/> representing the stream.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="filePath"/> is <see langword="null"/> or an empty string.
|
||||
/// </exception>
|
||||
/// <exception cref="FileNotFoundException">
|
||||
/// The specified <paramref name="filePath"/> was not found.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <para><paramref name="filePath"/> is not a valid file path.</para>
|
||||
/// <para>-or-</para>
|
||||
/// <para><paramref name="streamName"/> contains invalid characters.</para>
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
public static AlternateDataStreamInfo GetAlternateDataStream(string filePath, string streamName)
|
||||
{
|
||||
return GetAlternateDataStream(filePath, streamName, FileMode.OpenOrCreate);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Delete Stream
|
||||
|
||||
/// <summary>
|
||||
/// <span style="font-weight:bold;color:#a00;">(Extension Method)</span><br />
|
||||
/// Deletes the specified alternate data stream if it exists.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// The <see cref="FileInfo"/> to inspect.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream to delete.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the specified stream is deleted;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="streamName"/> contains invalid characters.
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
public static bool DeleteAlternateDataStream(this FileSystemInfo file, string streamName)
|
||||
{
|
||||
if (null == file) throw new ArgumentNullException("file");
|
||||
SafeNativeMethods.ValidateStreamName(streamName);
|
||||
|
||||
const FileIOPermissionAccess permAccess = FileIOPermissionAccess.Write;
|
||||
new FileIOPermission(permAccess, file.FullName).Demand();
|
||||
|
||||
var result = false;
|
||||
if (file.Exists)
|
||||
{
|
||||
string path = SafeNativeMethods.BuildStreamPath(file.FullName, streamName);
|
||||
if (-1 != SafeNativeMethods.SafeGetFileAttributes(path))
|
||||
{
|
||||
result = SafeNativeMethods.SafeDeleteFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified alternate data stream if it exists.
|
||||
/// </summary>
|
||||
/// <param name="filePath">
|
||||
/// The path of the file to inspect.
|
||||
/// </param>
|
||||
/// <param name="streamName">
|
||||
/// The name of the stream to find.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the specified stream is deleted;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="filePath"/> is <see langword="null"/> or an empty string.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <para><paramref name="filePath"/> is not a valid file path.</para>
|
||||
/// <para>-or-</para>
|
||||
/// <para><paramref name="streamName"/> contains invalid characters.</para>
|
||||
/// </exception>
|
||||
/// <exception cref="SecurityException">
|
||||
/// The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="UnauthorizedAccessException">
|
||||
/// The caller does not have the required permission, or the file is read-only.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">
|
||||
/// The specified file is in use.
|
||||
/// </exception>
|
||||
public static bool DeleteAlternateDataStream(string filePath, string streamName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath");
|
||||
return CreateInfo(filePath).DeleteAlternateDataStream(streamName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
118
@integrate/Trinet.Core.IO.Ntfs/SafeHGlobalHandle.cs
Normal file
118
@integrate/Trinet.Core.IO.Ntfs/SafeHGlobalHandle.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Trinet.Core.IO.Ntfs
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="SafeHandle"/> for a global memory allocation.
|
||||
/// </summary>
|
||||
internal sealed class SafeHGlobalHandle : SafeHandle
|
||||
{
|
||||
#region Private Data
|
||||
|
||||
private readonly int _size;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SafeHGlobalHandle"/> class.
|
||||
/// </summary>
|
||||
/// <param name="toManage">
|
||||
/// The initial handle value.
|
||||
/// </param>
|
||||
/// <param name="size">
|
||||
/// The size of this memory block, in bytes.
|
||||
/// </param>
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
private SafeHGlobalHandle(IntPtr toManage, int size) : base(IntPtr.Zero, true)
|
||||
{
|
||||
_size = size;
|
||||
base.SetHandle(toManage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SafeHGlobalHandle"/> class.
|
||||
/// </summary>
|
||||
private SafeHGlobalHandle() : base(IntPtr.Zero, true)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the handle value is invalid.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true"/> if the handle value is invalid;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </value>
|
||||
public override bool IsInvalid
|
||||
{
|
||||
get { return IntPtr.Zero == base.handle; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the size of this memory block.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size of this memory block, in bytes.
|
||||
/// </value>
|
||||
public int Size
|
||||
{
|
||||
get { return _size; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Allocates memory from the unmanaged memory of the process using GlobalAlloc.
|
||||
/// </summary>
|
||||
/// <param name="bytes">
|
||||
/// The number of bytes in memory required.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="SafeHGlobalHandle"/> representing the memory.
|
||||
/// </returns>
|
||||
/// <exception cref="OutOfMemoryException">
|
||||
/// There is insufficient memory to satisfy the request.
|
||||
/// </exception>
|
||||
public static SafeHGlobalHandle Allocate(int bytes)
|
||||
{
|
||||
return new SafeHGlobalHandle(Marshal.AllocHGlobal(bytes), bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an invalid handle.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An invalid <see cref="SafeHGlobalHandle"/>.
|
||||
/// </returns>
|
||||
public static SafeHGlobalHandle Invalid()
|
||||
{
|
||||
return new SafeHGlobalHandle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the code required to free the handle.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the handle is released successfully;
|
||||
/// otherwise, in the event of a catastrophic failure, <see langword="false"/>.
|
||||
/// In this case, it generates a releaseHandleFailed MDA Managed Debugging Assistant.
|
||||
/// </returns>
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
Marshal.FreeHGlobal(base.handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
478
@integrate/Trinet.Core.IO.Ntfs/SafeNativeMethods.cs
Normal file
478
@integrate/Trinet.Core.IO.Ntfs/SafeNativeMethods.cs
Normal file
@@ -0,0 +1,478 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
namespace Trinet.Core.IO.Ntfs
|
||||
{
|
||||
using Resources = Properties.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// Safe native methods.
|
||||
/// </summary>
|
||||
internal static class SafeNativeMethods
|
||||
{
|
||||
#region Constants and flags
|
||||
|
||||
public const int MaxPath = 256;
|
||||
private const string LongPathPrefix = @"\\?\";
|
||||
public const char StreamSeparator = ':';
|
||||
public const int DefaultBufferSize = 0x1000;
|
||||
|
||||
private const int ErrorFileNotFound = 2;
|
||||
|
||||
// "Characters whose integer representations are in the range from 1 through 31,
|
||||
// except for alternate streams where these characters are allowed"
|
||||
// http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx
|
||||
private static readonly char[] InvalidStreamNameChars = Path.GetInvalidFileNameChars().Where(c => c < 1 || c > 31).ToArray();
|
||||
|
||||
[Flags]
|
||||
public enum NativeFileFlags : uint
|
||||
{
|
||||
WriteThrough = 0x80000000,
|
||||
Overlapped = 0x40000000,
|
||||
NoBuffering = 0x20000000,
|
||||
RandomAccess = 0x10000000,
|
||||
SequentialScan = 0x8000000,
|
||||
DeleteOnClose = 0x4000000,
|
||||
BackupSemantics = 0x2000000,
|
||||
PosixSemantics = 0x1000000,
|
||||
OpenReparsePoint = 0x200000,
|
||||
OpenNoRecall = 0x100000
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum NativeFileAccess : uint
|
||||
{
|
||||
GenericRead = 0x80000000,
|
||||
GenericWrite = 0x40000000
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region P/Invoke Structures
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct LargeInteger
|
||||
{
|
||||
public readonly int Low;
|
||||
public readonly int High;
|
||||
|
||||
public long ToInt64()
|
||||
{
|
||||
return (this.High * 0x100000000) + this.Low;
|
||||
}
|
||||
|
||||
/*
|
||||
public static LargeInteger FromInt64(long value)
|
||||
{
|
||||
return new LargeInteger
|
||||
{
|
||||
Low = (int)(value & 0x11111111),
|
||||
High = (int)((value / 0x100000000) & 0x11111111)
|
||||
};
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct Win32StreamId
|
||||
{
|
||||
public readonly int StreamId;
|
||||
public readonly int StreamAttributes;
|
||||
public LargeInteger Size;
|
||||
public readonly int StreamNameSize;
|
||||
}
|
||||
|
||||
/*
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct FileInformationByHandle
|
||||
{
|
||||
public int dwFileAttributes;
|
||||
public LargeInteger ftCreationTime;
|
||||
public LargeInteger ftLastAccessTime;
|
||||
public LargeInteger ftLastWriteTime;
|
||||
public int dwVolumeSerialNumber;
|
||||
public LargeInteger FileSize;
|
||||
public int nNumberOfLinks;
|
||||
public LargeInteger FileIndex;
|
||||
}
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region P/Invoke Methods
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||
private static extern int FormatMessage(
|
||||
int dwFlags,
|
||||
IntPtr lpSource,
|
||||
int dwMessageId,
|
||||
int dwLanguageId,
|
||||
StringBuilder lpBuffer,
|
||||
int nSize,
|
||||
IntPtr vaListArguments);
|
||||
|
||||
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern int GetFileAttributes(string fileName);
|
||||
|
||||
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool GetFileSizeEx(SafeFileHandle handle, out LargeInteger size);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern int GetFileType(SafeFileHandle handle);
|
||||
|
||||
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern SafeFileHandle CreateFile(
|
||||
string name,
|
||||
NativeFileAccess access,
|
||||
FileShare share,
|
||||
IntPtr security,
|
||||
FileMode mode,
|
||||
NativeFileFlags flags,
|
||||
IntPtr template);
|
||||
|
||||
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool DeleteFile(string name);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool BackupRead(
|
||||
SafeFileHandle hFile,
|
||||
ref Win32StreamId pBuffer,
|
||||
int numberOfBytesToRead,
|
||||
out int numberOfBytesRead,
|
||||
[MarshalAs(UnmanagedType.Bool)] bool abort,
|
||||
[MarshalAs(UnmanagedType.Bool)] bool processSecurity,
|
||||
ref IntPtr context);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool BackupRead(
|
||||
SafeFileHandle hFile,
|
||||
SafeHGlobalHandle pBuffer,
|
||||
int numberOfBytesToRead,
|
||||
out int numberOfBytesRead,
|
||||
[MarshalAs(UnmanagedType.Bool)] bool abort,
|
||||
[MarshalAs(UnmanagedType.Bool)] bool processSecurity,
|
||||
ref IntPtr context);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool BackupSeek(
|
||||
SafeFileHandle hFile,
|
||||
int bytesToSeekLow,
|
||||
int bytesToSeekHigh,
|
||||
out int bytesSeekedLow,
|
||||
out int bytesSeekedHigh,
|
||||
ref IntPtr context);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utility Structures
|
||||
|
||||
public struct Win32StreamInfo
|
||||
{
|
||||
public FileStreamType StreamType;
|
||||
public FileStreamAttributes StreamAttributes;
|
||||
public long StreamSize;
|
||||
public string StreamName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utility Methods
|
||||
|
||||
private static int MakeHRFromErrorCode(int errorCode)
|
||||
{
|
||||
return (-2147024896 | errorCode);
|
||||
}
|
||||
|
||||
private static string GetErrorMessage(int errorCode)
|
||||
{
|
||||
var lpBuffer = new StringBuilder(0x200);
|
||||
if (0 != FormatMessage(0x3200, IntPtr.Zero, errorCode, 0, lpBuffer, lpBuffer.Capacity, IntPtr.Zero))
|
||||
{
|
||||
return lpBuffer.ToString();
|
||||
}
|
||||
|
||||
return string.Format(Resources.Culture, Resources.Error_UnknownError, errorCode);
|
||||
}
|
||||
|
||||
private static void ThrowIOError(int errorCode, string path)
|
||||
{
|
||||
switch (errorCode)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 2: // File not found
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) throw new FileNotFoundException();
|
||||
throw new FileNotFoundException(null, path);
|
||||
}
|
||||
case 3: // Directory not found
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) throw new DirectoryNotFoundException();
|
||||
throw new DirectoryNotFoundException(string.Format(Resources.Culture, Resources.Error_DirectoryNotFound, path));
|
||||
}
|
||||
case 5: // Access denied
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) throw new UnauthorizedAccessException();
|
||||
throw new UnauthorizedAccessException(string.Format(Resources.Culture, Resources.Error_AccessDenied_Path, path));
|
||||
}
|
||||
case 15: // Drive not found
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) throw new DriveNotFoundException();
|
||||
throw new DriveNotFoundException(string.Format(Resources.Culture, Resources.Error_DriveNotFound, path));
|
||||
}
|
||||
case 32: // Sharing violation
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) throw new IOException(GetErrorMessage(errorCode), MakeHRFromErrorCode(errorCode));
|
||||
throw new IOException(string.Format(Resources.Culture, Resources.Error_SharingViolation, path), MakeHRFromErrorCode(errorCode));
|
||||
}
|
||||
case 80: // File already exists
|
||||
{
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new IOException(string.Format(Resources.Culture, Resources.Error_FileAlreadyExists, path), MakeHRFromErrorCode(errorCode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 87: // Invalid parameter
|
||||
{
|
||||
throw new IOException(GetErrorMessage(errorCode), MakeHRFromErrorCode(errorCode));
|
||||
}
|
||||
case 183: // File or directory already exists
|
||||
{
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new IOException(string.Format(Resources.Culture, Resources.Error_AlreadyExists, path), MakeHRFromErrorCode(errorCode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 206: // Path too long
|
||||
{
|
||||
throw new PathTooLongException();
|
||||
}
|
||||
case 995: // Operation cancelled
|
||||
{
|
||||
throw new OperationCanceledException();
|
||||
}
|
||||
default:
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(MakeHRFromErrorCode(errorCode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ThrowLastIOError(string path)
|
||||
{
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
if (0 != errorCode)
|
||||
{
|
||||
int hr = Marshal.GetHRForLastWin32Error();
|
||||
if (0 <= hr) throw new Win32Exception(errorCode);
|
||||
ThrowIOError(errorCode, path);
|
||||
}
|
||||
}
|
||||
|
||||
public static NativeFileAccess ToNative(this FileAccess access)
|
||||
{
|
||||
NativeFileAccess result = 0;
|
||||
if (FileAccess.Read == (FileAccess.Read & access)) result |= NativeFileAccess.GenericRead;
|
||||
if (FileAccess.Write == (FileAccess.Write & access)) result |= NativeFileAccess.GenericWrite;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string BuildStreamPath(string filePath, string streamName)
|
||||
{
|
||||
string result = filePath;
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
if (1 == result.Length) result = ".\\" + result;
|
||||
result += StreamSeparator + streamName + StreamSeparator + "$DATA";
|
||||
if (MaxPath <= result.Length) result = LongPathPrefix + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void ValidateStreamName(string streamName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(streamName) && -1 != streamName.IndexOfAny(InvalidStreamNameChars))
|
||||
{
|
||||
throw new ArgumentException(Resources.Error_InvalidFileChars);
|
||||
}
|
||||
}
|
||||
|
||||
public static int SafeGetFileAttributes(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
|
||||
|
||||
int result = GetFileAttributes(name);
|
||||
if (-1 == result)
|
||||
{
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
if (ErrorFileNotFound != errorCode) ThrowLastIOError(name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool SafeDeleteFile(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
|
||||
|
||||
bool result = DeleteFile(name);
|
||||
if (!result)
|
||||
{
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
if (ErrorFileNotFound != errorCode) ThrowLastIOError(name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SafeFileHandle SafeCreateFile(string path, NativeFileAccess access, FileShare share, IntPtr security, FileMode mode, NativeFileFlags flags, IntPtr template)
|
||||
{
|
||||
SafeFileHandle result = CreateFile(path, access, share, security, mode, flags, template);
|
||||
if (!result.IsInvalid && 1 != GetFileType(result))
|
||||
{
|
||||
result.Dispose();
|
||||
throw new NotSupportedException(string.Format(Resources.Culture,
|
||||
Resources.Error_NonFile, path));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static long GetFileSize(string path, SafeFileHandle handle)
|
||||
{
|
||||
long result = 0L;
|
||||
if (null != handle && !handle.IsInvalid)
|
||||
{
|
||||
LargeInteger value;
|
||||
if (GetFileSizeEx(handle, out value))
|
||||
{
|
||||
result = value.ToInt64();
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowLastIOError(path);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static long GetFileSize(string path)
|
||||
{
|
||||
long result = 0L;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
using (SafeFileHandle handle = SafeCreateFile(path, NativeFileAccess.GenericRead, FileShare.Read, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero))
|
||||
{
|
||||
result = GetFileSize(path, handle);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IList<Win32StreamInfo> ListStreams(string filePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath");
|
||||
if (-1 != filePath.IndexOfAny(Path.GetInvalidPathChars())) throw new ArgumentException(Resources.Error_InvalidFileChars, "filePath");
|
||||
|
||||
var result = new List<Win32StreamInfo>();
|
||||
|
||||
using (SafeFileHandle hFile = SafeCreateFile(filePath, NativeFileAccess.GenericRead, FileShare.Read, IntPtr.Zero, FileMode.Open, NativeFileFlags.BackupSemantics, IntPtr.Zero))
|
||||
using (var hName = new StreamName())
|
||||
{
|
||||
if (!hFile.IsInvalid)
|
||||
{
|
||||
var streamId = new Win32StreamId();
|
||||
int dwStreamHeaderSize = Marshal.SizeOf(streamId);
|
||||
bool finished = false;
|
||||
IntPtr context = IntPtr.Zero;
|
||||
int bytesRead;
|
||||
string name;
|
||||
|
||||
try
|
||||
{
|
||||
while (!finished)
|
||||
{
|
||||
// Read the next stream header:
|
||||
if (!BackupRead(hFile, ref streamId, dwStreamHeaderSize, out bytesRead, false, false, ref context))
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
else if (dwStreamHeaderSize != bytesRead)
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read the stream name:
|
||||
if (0 >= streamId.StreamNameSize)
|
||||
{
|
||||
name = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
hName.EnsureCapacity(streamId.StreamNameSize);
|
||||
if (!BackupRead(hFile, hName.MemoryBlock, streamId.StreamNameSize, out bytesRead, false, false, ref context))
|
||||
{
|
||||
name = null;
|
||||
finished = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unicode chars are 2 bytes:
|
||||
name = hName.ReadStreamName(bytesRead >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the stream info to the result:
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
result.Add(new Win32StreamInfo
|
||||
{
|
||||
StreamType = (FileStreamType)streamId.StreamId,
|
||||
StreamAttributes = (FileStreamAttributes)streamId.StreamAttributes,
|
||||
StreamSize = streamId.Size.ToInt64(),
|
||||
StreamName = name
|
||||
});
|
||||
}
|
||||
|
||||
// Skip the contents of the stream:
|
||||
int bytesSeekedLow, bytesSeekedHigh;
|
||||
if (!finished && !BackupSeek(hFile, streamId.Size.Low, streamId.Size.High, out bytesSeekedLow, out bytesSeekedHigh, ref context))
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Abort the backup:
|
||||
BackupRead(hFile, hName.MemoryBlock, 0, out bytesRead, true, false, ref context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
134
@integrate/Trinet.Core.IO.Ntfs/StreamName.cs
Normal file
134
@integrate/Trinet.Core.IO.Ntfs/StreamName.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Trinet.Core.IO.Ntfs
|
||||
{
|
||||
internal sealed class StreamName : IDisposable
|
||||
{
|
||||
#region Private Data
|
||||
|
||||
private static readonly SafeHGlobalHandle _invalidBlock = SafeHGlobalHandle.Invalid();
|
||||
private SafeHGlobalHandle _memoryBlock = _invalidBlock;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StreamName"/> class.
|
||||
/// </summary>
|
||||
public StreamName()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Returns the handle to the block of memory.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The <see cref="SafeHGlobalHandle"/> representing the block of memory.
|
||||
/// </value>
|
||||
public SafeHGlobalHandle MemoryBlock
|
||||
{
|
||||
get { return _memoryBlock; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing,
|
||||
/// releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_memoryBlock.IsInvalid)
|
||||
{
|
||||
_memoryBlock.Dispose();
|
||||
_memoryBlock = _invalidBlock;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that there is sufficient memory allocated.
|
||||
/// </summary>
|
||||
/// <param name="capacity">
|
||||
/// The required capacity of the block, in bytes.
|
||||
/// </param>
|
||||
/// <exception cref="OutOfMemoryException">
|
||||
/// There is insufficient memory to satisfy the request.
|
||||
/// </exception>
|
||||
public void EnsureCapacity(int capacity)
|
||||
{
|
||||
int currentSize = _memoryBlock.IsInvalid ? 0 : _memoryBlock.Size;
|
||||
if (capacity > currentSize)
|
||||
{
|
||||
if (0 != currentSize) currentSize <<= 1;
|
||||
if (capacity > currentSize) currentSize = capacity;
|
||||
|
||||
if (!_memoryBlock.IsInvalid) _memoryBlock.Dispose();
|
||||
_memoryBlock = SafeHGlobalHandle.Allocate(currentSize);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the Unicode string from the memory block.
|
||||
/// </summary>
|
||||
/// <param name="length">
|
||||
/// The length of the string to read, in characters.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The string read from the memory block.
|
||||
/// </returns>
|
||||
public string ReadString(int length)
|
||||
{
|
||||
if (0 >= length || _memoryBlock.IsInvalid) return null;
|
||||
if (length > _memoryBlock.Size) length = _memoryBlock.Size;
|
||||
return Marshal.PtrToStringUni(_memoryBlock.DangerousGetHandle(), length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the string, and extracts the stream name.
|
||||
/// </summary>
|
||||
/// <param name="length">
|
||||
/// The length of the string to read, in characters.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The stream name.
|
||||
/// </returns>
|
||||
public string ReadStreamName(int length)
|
||||
{
|
||||
string name = this.ReadString(length);
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
// Name is of the format ":NAME:$DATA\0"
|
||||
int separatorIndex = name.IndexOf(SafeNativeMethods.StreamSeparator, 1);
|
||||
if (-1 != separatorIndex)
|
||||
{
|
||||
name = name.Substring(1, separatorIndex - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should never happen!
|
||||
separatorIndex = name.IndexOf('\0');
|
||||
if (1 < separatorIndex)
|
||||
{
|
||||
name = name.Substring(1, separatorIndex - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
322
@integrate/WCFHost.cs
Normal file
322
@integrate/WCFHost.cs
Normal file
@@ -0,0 +1,322 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ServiceModel;
|
||||
using Watchdog.WatchdogLib.Monitor;
|
||||
using Watchdog.WatchdogLib.WinForms;
|
||||
|
||||
namespace Watchdog
|
||||
{
|
||||
/// <summary>
|
||||
/// WCF Operations Contract in order to allow the command-line process
|
||||
/// to communicate with the running Application's instance
|
||||
/// </summary>
|
||||
[ServiceContract]
|
||||
public interface IWatchdog
|
||||
{
|
||||
#region Application State Changes
|
||||
|
||||
/// <summary>
|
||||
/// Starts Monitoring
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void StartMonitoring();
|
||||
|
||||
/// <summary>
|
||||
/// Pauses Monitoring
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void PauseMonitoring();
|
||||
|
||||
/// <summary>
|
||||
/// Restarts Monitoring
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void RestartMonitoring();
|
||||
|
||||
/// <summary>
|
||||
/// Restarts All Monitoring
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void RestartAllMonitoring();
|
||||
|
||||
/// <summary>
|
||||
/// Stops Monitoring
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void StopMonitoring();
|
||||
|
||||
/// <summary>
|
||||
/// Stops All Monitoring
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void StopAllMonitoring();
|
||||
|
||||
/// <summary>
|
||||
/// Tell the Running Application to Reload the Configuration
|
||||
/// </summary>
|
||||
[OperationContract]
|
||||
void ReloadConfigurationNextInterval();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ping
|
||||
|
||||
/// <summary>
|
||||
/// To Check if we can communicate with the other side
|
||||
/// </summary>
|
||||
/// <returns>PING_RETURN_VALUE</returns>
|
||||
[OperationContract]
|
||||
int Ping();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for the WCF Callbacks
|
||||
/// </summary>
|
||||
public class WCFHost : IWatchdog
|
||||
{
|
||||
#region IWatchdog Members
|
||||
|
||||
/// <summary>
|
||||
/// Starts Monitoring
|
||||
/// </summary>
|
||||
public void StartMonitoring()
|
||||
{
|
||||
HiddenMainWindow.StartMonitoring(true, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses Monitoring
|
||||
/// </summary>
|
||||
public void PauseMonitoring()
|
||||
{
|
||||
HiddenMainWindow.PauseMonitoring(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restarts Monitoring
|
||||
/// </summary>
|
||||
public void RestartMonitoring()
|
||||
{
|
||||
HiddenMainWindow.RestartMonitoring(4, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restarts All Monitoring
|
||||
/// </summary>
|
||||
public void RestartAllMonitoring()
|
||||
{
|
||||
HiddenMainWindow.RestartAllMonitoring(4, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops Monitoring
|
||||
/// </summary>
|
||||
public void StopMonitoring()
|
||||
{
|
||||
HiddenMainWindow.StopMonitoring(true, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops All Monitoring
|
||||
/// </summary>
|
||||
public void StopAllMonitoring()
|
||||
{
|
||||
HiddenMainWindow.StopAllMonitoring(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tell the Running Application to Reload the Configuration
|
||||
/// </summary>
|
||||
public void ReloadConfigurationNextInterval()
|
||||
{
|
||||
App.xmlfile.ForceRefreshOnNext_ReadData = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Const Value to return on Ping
|
||||
/// </summary>
|
||||
public const int PING_RETURN_VALUE = 10;
|
||||
/// <summary>
|
||||
/// To Check if we can communicate with the other side
|
||||
/// </summary>
|
||||
/// <returns>PING_RETURN_VALUE</returns>
|
||||
public int Ping()
|
||||
{
|
||||
return PING_RETURN_VALUE;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Configuration Changes / Display Configuration Statics
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Process from the Configuration and saves the xml
|
||||
/// </summary>
|
||||
/// <param name="ProcessExeFileNameNPath">Process Exe File name</param>
|
||||
/// <param name="CommandlinePrms">Command Line Prms for Process</param>
|
||||
/// <param name="WorkingDir">Working Directory</param>
|
||||
/// <returns>true if successfull, false otherwise</returns>
|
||||
public static bool AddProcess(string ProcessExeFileNameNPath, string CommandlinePrms, string WorkingDir)
|
||||
{
|
||||
WatchdogConfiguration config = App.xmlfile.ReadData(false);
|
||||
bool bSuccess = config.MonitoredProcesses.AddProcessExe(ProcessExeFileNameNPath, CommandlinePrms, WorkingDir);
|
||||
if (bSuccess)
|
||||
App.xmlfile.SaveData();
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a Process from the Configuration and saves the xml
|
||||
/// </summary>
|
||||
/// <param name="ProcessExeFileNameNPath">Process Exe File name</param>
|
||||
/// <param name="CommandlinePrms">Command Line Prms for Process</param>
|
||||
/// <returns>true if successfully deleted a process with matching ProcessExeFileNameNPath and CommandlinePrms</returns>
|
||||
public static bool RemoveProcess(string ProcessExeFileNameNPath, string CommandlinePrms)
|
||||
{
|
||||
WatchdogConfiguration config = App.xmlfile.ReadData(false);
|
||||
bool bSuccess = config.MonitoredProcesses.RemoveProcessExe(ProcessExeFileNameNPath, CommandlinePrms);
|
||||
if (bSuccess)
|
||||
App.xmlfile.SaveData();
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Service from the configuration and saves the xml
|
||||
/// </summary>
|
||||
/// <param name="ServiceName">Name of Service</param>
|
||||
/// <returns>true if sucessfull, false otherwise</returns>
|
||||
public static bool AddService(string ServiceName)
|
||||
{
|
||||
WatchdogConfiguration config = App.xmlfile.ReadData(false);
|
||||
bool bSuccess = config.MonitoredServices.AddServiceExe(ServiceName);
|
||||
if (bSuccess)
|
||||
App.xmlfile.SaveData();
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a Service from the configuration and saves the xml
|
||||
/// </summary>
|
||||
/// <param name="ServiceName">Name of Service</param>
|
||||
/// <returns>true if sucessfull, false otherwise</returns>
|
||||
public static bool RemoveService(string ServiceName)
|
||||
{
|
||||
WatchdogConfiguration config = App.xmlfile.ReadData(false);
|
||||
bool bSuccess = config.MonitoredServices.RemoveServiceExe(ServiceName);
|
||||
if (bSuccess)
|
||||
App.xmlfile.SaveData();
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of all Processes and their configurations (in a ';' seperated string)
|
||||
/// </summary>
|
||||
/// <returns>Process List with configuration</returns>
|
||||
public static string[] ShowProcesses()
|
||||
{
|
||||
List<string> ProcessList = new List<String>();
|
||||
WatchdogConfiguration config = App.xmlfile.ReadData(false);
|
||||
string s = String.Empty;
|
||||
foreach (WatchdogConfiguration.ProcessExe p in config.MonitoredProcesses.ProcessExes)
|
||||
{
|
||||
if (String.IsNullOrEmpty(p.CommandLinePrms) && String.IsNullOrEmpty(p.WorkingDirectory))
|
||||
s = p.ProcessExeFileNameNPath;
|
||||
else if (!String.IsNullOrEmpty(p.CommandLinePrms) && String.IsNullOrEmpty(p.WorkingDirectory))
|
||||
s = p.ProcessExeFileNameNPath + ";" + p.CommandLinePrms;
|
||||
else if (!String.IsNullOrEmpty(p.CommandLinePrms) && !String.IsNullOrEmpty(p.WorkingDirectory))
|
||||
s = p.ProcessExeFileNameNPath + ";" + p.CommandLinePrms + ";" + p.WorkingDirectory;
|
||||
else
|
||||
continue;
|
||||
ProcessList.Add(s);
|
||||
}
|
||||
return ProcessList.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of all Services
|
||||
/// </summary>
|
||||
/// <returns>Services List</returns>
|
||||
public static string[] ShowServices()
|
||||
{
|
||||
List<string> ProcessList = new List<String>();
|
||||
WatchdogConfiguration config = App.xmlfile.ReadData(false);
|
||||
foreach (WatchdogConfiguration.ServiceExe s in config.MonitoredServices.ServiceExes)
|
||||
ProcessList.Add(s.Name);
|
||||
return ProcessList.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Statics
|
||||
|
||||
private static ServiceHost _host = null;
|
||||
|
||||
/// <summary>
|
||||
/// Start the WCF Pipe Host (Watchdog)
|
||||
/// </summary>
|
||||
internal static void StartHost()
|
||||
{
|
||||
// Make sure it is closed
|
||||
StopHost();
|
||||
_host = new ServiceHost(typeof(WCFHost), new Uri[] { new Uri("net.pipe://localhost") });
|
||||
_host.AddServiceEndpoint(typeof(IWatchdog), new NetNamedPipeBinding(), AppResx.GetString("APPLICATION_NAME_SHORT"));
|
||||
|
||||
try
|
||||
{
|
||||
_host.Open();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
App.log.Fatal("Unable to start WCF Pipe Host", e);
|
||||
MsgBox.ShowFatalError("Unable to start WCF Pipe Host", "Pipe Host Failure", System.Windows.Forms.MessageBoxButtons.OK);
|
||||
App.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the WCF Pipe Host
|
||||
/// </summary>
|
||||
internal static void StopHost()
|
||||
{
|
||||
if (_host != null)
|
||||
{
|
||||
_host.Close();
|
||||
_host = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by Client to communicate with the server
|
||||
/// </summary>
|
||||
/// <returns>a valid IWatchDog Object or Null if error occured</returns>
|
||||
internal static IWatchdog GetWatchDogClientInterface()
|
||||
{
|
||||
// We only should be calling this in CommandLine Mode.
|
||||
if (App.State_SpecialMode_IsCommandLineSet())
|
||||
{
|
||||
try
|
||||
{
|
||||
IWatchdog watchdoginterface = null;
|
||||
ChannelFactory<IWatchdog> iwatchdogFactory = new ChannelFactory<IWatchdog>(new NetNamedPipeBinding(), new EndpointAddress(("net.pipe://localhost/" + AppResx.GetString("APPLICATION_NAME_SHORT"))));
|
||||
watchdoginterface = iwatchdogFactory.CreateChannel();
|
||||
|
||||
// Try to ping the object! ~if it fails, target object doesn't exist
|
||||
if (watchdoginterface.Ping() == WCFHost.PING_RETURN_VALUE)
|
||||
return watchdoginterface;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// * Ignore this error we don't want to log this*
|
||||
//App.log.Error("Failed to obtain WatchDogClientInterface", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user