diff --git a/AutoTx/ATXProject.csproj b/AutoTx/ATXProject.csproj index 65e71b0874ea64f5b6c81d7024fb45702597e911..5d3ca82039312efa17dffc96974af331c30b88c0 100644 --- a/AutoTx/ATXProject.csproj +++ b/AutoTx/ATXProject.csproj @@ -105,9 +105,6 @@ <Compile Include="SystemChecks.cs"> <SubType>Component</SubType> </Compile> - <Compile Include="XmlWrapper\DriveToCheck.cs" /> - <Compile Include="XmlWrapper\ServiceConfig.cs" /> - <Compile Include="XmlWrapper\ServiceStatus.cs" /> </ItemGroup> <ItemGroup> <None Include="App.config" /> @@ -150,6 +147,12 @@ <ItemGroup> <None Include="Resources\BuildCommit.txt" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\ATXSerializables\ATXSerializables.csproj"> + <Project>{166D65D5-EE10-4364-8AA3-4D86BA5CE244}</Project> + <Name>ATXSerializables</Name> + </ProjectReference> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <PropertyGroup> <PreBuildEvent>PowerShell -NoProfile -ExecutionPolicy RemoteSigned $(SolutionDir)\Scripts\Prepare-Build.ps1 $(ProjectDir)</PreBuildEvent> diff --git a/AutoTx/AutoTx.cs b/AutoTx/AutoTx.cs index b633804741d959db1b2ffd44c60e7f76cb85ac99..f75e424dbe8fa915b3b076e39aaf542d094c6509 100644 --- a/AutoTx/AutoTx.cs +++ b/AutoTx/AutoTx.cs @@ -9,7 +9,7 @@ using System.Timers; using System.DirectoryServices.AccountManagement; using System.Globalization; using System.Management; -using AutoTx.XmlWrapper; +using ATXSerializables; using RoboSharp; namespace AutoTx diff --git a/AutoTx/XmlWrapper/DriveToCheck.cs b/AutoTx/XmlWrapper/DriveToCheck.cs deleted file mode 100644 index 5455a6c69cfdc093ff1e0d59675e7e6a586d4f4e..0000000000000000000000000000000000000000 --- a/AutoTx/XmlWrapper/DriveToCheck.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Xml.Serialization; - -namespace AutoTx.XmlWrapper -{ - /// <summary> - /// Helper class for the nested SpaceMonitoring sections. - /// </summary> - public class DriveToCheck - { - [XmlElement("DriveName")] - public string DriveName { get; set; } - - // the value is to be compared to System.IO.DriveInfo.TotalFreeSpace - // hence we use the same type (long) to avoid unnecessary casts later: - [XmlElement("SpaceThreshold")] - public long SpaceThreshold { get; set; } - } -} \ No newline at end of file diff --git a/AutoTx/XmlWrapper/ServiceConfig.cs b/AutoTx/XmlWrapper/ServiceConfig.cs deleted file mode 100644 index 0006b1f6ade03b6424be71a8dc59d52d379e364d..0000000000000000000000000000000000000000 --- a/AutoTx/XmlWrapper/ServiceConfig.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.IO; -using System.Xml.Serialization; - -namespace AutoTx.XmlWrapper -{ - /// <summary> - /// configuration class based on xml - /// </summary> - [Serializable] - public class ServiceConfig - { - [XmlIgnore] public string ValidationWarnings; - - public ServiceConfig() { - ValidationWarnings = ""; - // set values for the optional XML elements: - SmtpHost = ""; - SmtpPort = 25; - SmtpUserCredential = ""; - SmtpPasswortCredential = ""; - EmailPrefix = ""; - AdminEmailAdress = ""; - AdminDebugEmailAdress = ""; - GraceNotificationDelta = 720; - - InterPacketGap = 0; - - EnforceInheritedACLs = true; - } - - #region required configuration parameters - - /// <summary> - /// A human friendly name for the host, to be used in emails etc. - /// </summary> - public string HostAlias { get; set; } - - /// <summary> - /// A human friendly name for the target, to be used in emails etc. - /// </summary> - public string DestinationAlias { get; set; } - - /// <summary> - /// The base drive for the spooling directories (incoming and managed). - /// </summary> - public string SourceDrive { get; set; } - - /// <summary> - /// The name of a directory on SourceDrive that is monitored for new files. - /// </summary> - public string IncomingDirectory { get; set; } - - /// <summary> - /// The name of a marker file to be placed in all **sub**directories - /// inside the IncomingDirectory. - /// </summary> - public string MarkerFile { get; set; } - - /// <summary> - /// A directory on SourceDrive to hold the three subdirectories "DONE", - /// "PROCESSING" and "UNMATCHED" used during and after transfers. - /// </summary> - public string ManagedDirectory { get; set; } - - /// <summary> - /// Target path to transfer files to. Usually a UNC location. - /// </summary> - public string DestinationDirectory { get; set; } - - /// <summary> - /// The name of a subdirectory in the DestinationDirectory to be used - /// to keep the temporary data of running transfers. - /// </summary> - public string TmpTransferDir { get; set; } - - public string EmailFrom { get; set; } - - public int ServiceTimer { get; set; } - - public int MaxCpuUsage { get; set; } - public int MinAvailableMemory { get; set; } - public int AdminNotificationDelta { get; set; } - public int StorageNotificationDelta { get; set; } - - /// <summary> - /// GracePeriod: number of days after data in the "DONE" location expires, - /// which will trigger a summary email to the admin address. - /// </summary> - public int GracePeriod { get; set; } - - public bool SendAdminNotification { get; set; } - public bool SendTransferNotification { get; set; } - public bool Debug { get; set; } - - [XmlArray] - [XmlArrayItem(ElementName = "DriveToCheck")] - public List<DriveToCheck> SpaceMonitoring { get; set; } - - [XmlArray] - [XmlArrayItem(ElementName = "ProcessName")] - public List<string> BlacklistedProcesses { get; set; } - - #endregion - - - #region optional configuration parameters - - public string SmtpHost { get; set; } - public string SmtpUserCredential { get; set; } - public string SmtpPasswortCredential { get; set; } - public int SmtpPort { get; set; } - - public string EmailPrefix { get; set; } - public string AdminEmailAdress { get; set; } - public string AdminDebugEmailAdress { get; set; } - - public int GraceNotificationDelta { get; set; } - - public int InterPacketGap { get; set; } - - /// <summary> - /// EnforceInheritedACLs: whether to enforce ACL inheritance when moving files and - /// directories, see https://support.microsoft.com/en-us/help/320246 for more details. - /// </summary> - public bool EnforceInheritedACLs { get; set; } - - #endregion - - - public static void Serialize(string file, ServiceConfig c) { - // the config is never meant to be written by us, therefore: - throw new SettingsPropertyIsReadOnlyException("The config file must not be written by the service!"); - } - - public static ServiceConfig Deserialize(string file) { - var xs = new XmlSerializer(typeof(ServiceConfig)); - var reader = File.OpenText(file); - var config = (ServiceConfig) xs.Deserialize(reader); - reader.Close(); - ValidateConfiguration(config); - return config; - } - - private static void ValidateConfiguration(ServiceConfig c) { - if (string.IsNullOrEmpty(c.SourceDrive) || - string.IsNullOrEmpty(c.IncomingDirectory) || - string.IsNullOrEmpty(c.ManagedDirectory)) - throw new ConfigurationErrorsException("mandatory parameter missing!"); - - if (c.SourceDrive.Substring(1) != @":\") - throw new ConfigurationErrorsException("SourceDrive must be a drive " + - @"letter followed by a colon and a backslash, e.g. 'D:\'!"); - - // make sure SourceDrive is a local (fixed) disk: - var driveInfo = new DriveInfo(c.SourceDrive); - if (driveInfo.DriveType != DriveType.Fixed) - throw new ConfigurationErrorsException("SourceDrive (" + c.SourceDrive + - ") must be a local (fixed) drive, OS reports '" + driveInfo.DriveType + "')!"); - - - // spooling directories: IncomingDirectory + ManagedDirectory - if (c.IncomingDirectory.StartsWith(@"\")) - throw new ConfigurationErrorsException("IncomingDirectory must not start with a backslash!"); - if (c.ManagedDirectory.StartsWith(@"\")) - throw new ConfigurationErrorsException("ManagedDirectory must not start with a backslash!"); - - if (!Directory.Exists(c.DestinationDirectory)) - throw new ConfigurationErrorsException("can't find destination: " + c.DestinationDirectory); - - var tmpTransferPath = Path.Combine(c.DestinationDirectory, c.TmpTransferDir); - if (!Directory.Exists(tmpTransferPath)) - throw new ConfigurationErrorsException("temporary transfer dir doesn't exist: " + tmpTransferPath); - - if (c.ServiceTimer < 1000) - throw new ConfigurationErrorsException("ServiceTimer must not be smaller than 1000 ms!"); - - - // NON-CRITICAL stuff just adds messages to ValidationWarnings: - // DestinationDirectory - if (!c.DestinationDirectory.StartsWith(@"\\")) - c.ValidationWarnings += " - <DestinationDirectory> is not a UNC path!\n"; - } - - public string Summary() { - var msg = - "HostAlias: " + HostAlias + "\n" + - "SourceDrive: " + SourceDrive + "\n" + - "IncomingDirectory: " + IncomingDirectory + "\n" + - "MarkerFile: " + MarkerFile + "\n" + - "ManagedDirectory: " + ManagedDirectory + "\n" + - "GracePeriod: " + GracePeriod + "\n" + - "DestinationDirectory: " + DestinationDirectory + "\n" + - "TmpTransferDir: " + TmpTransferDir + "\n" + - "EnforceInheritedACLs: " + EnforceInheritedACLs + "\n" + - "ServiceTimer: " + ServiceTimer + "\n" + - "InterPacketGap: " + InterPacketGap + "\n" + - "MaxCpuUsage: " + MaxCpuUsage + "\n" + - "MinAvailableMemory: " + MinAvailableMemory + "\n"; - foreach (var processName in BlacklistedProcesses) { - msg += "BlacklistedProcess: " + processName + "\n"; - } - foreach (var driveToCheck in SpaceMonitoring) { - msg += "Drive to check free space: " + driveToCheck.DriveName + - " (threshold: " + driveToCheck.SpaceThreshold + ")" + "\n"; - } - if (string.IsNullOrEmpty(SmtpHost)) { - msg += "SmtpHost: ====== Not configured, disabling email! ======" + "\n"; - } else { - msg += - "SmtpHost: " + SmtpHost + "\n" + - "EmailFrom: " + EmailFrom + "\n" + - "AdminEmailAdress: " + AdminEmailAdress + "\n" + - "AdminDebugEmailAdress: " + AdminDebugEmailAdress + "\n" + - "StorageNotificationDelta: " + StorageNotificationDelta + "\n" + - "AdminNotificationDelta: " + AdminNotificationDelta + "\n" + - "GraceNotificationDelta: " + GraceNotificationDelta + "\n"; - } - return msg; - } - } -} \ No newline at end of file diff --git a/AutoTx/XmlWrapper/ServiceStatus.cs b/AutoTx/XmlWrapper/ServiceStatus.cs deleted file mode 100644 index 50c25439d958acfc7d32b8d5796eed0e62fb8ce7..0000000000000000000000000000000000000000 --- a/AutoTx/XmlWrapper/ServiceStatus.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System; -using System.IO; -using System.Xml.Serialization; - -namespace AutoTx.XmlWrapper -{ - [Serializable] - public class ServiceStatus - { - [XmlIgnore] string _storageFile; // remember where we came from - [XmlIgnore] private ServiceConfig _config; - [XmlIgnore] public string ValidationWarnings; - - private DateTime _lastStatusUpdate; - private DateTime _lastStorageNotification; - private DateTime _lastAdminNotification; - private DateTime _lastGraceNotification; - - private string _limitReason; - string _currentTransferSrc; - string _currentTargetTmp; - - bool _transferInProgress; - private bool _serviceSuspended; - private bool _cleanShutdown; - - private long _currentTransferSize; - - [XmlElement("LastStatusUpdate", DataType = "dateTime")] - public DateTime LastStatusUpdate { - get { return _lastStatusUpdate; } - set { _lastStatusUpdate = value; } - } - - [XmlElement("LastStorageNotification", DataType = "dateTime")] - public DateTime LastStorageNotification { - get { return _lastStorageNotification; } - set { - _lastStorageNotification = value; - Serialize(); - } - } - - [XmlElement("LastAdminNotification", DataType = "dateTime")] - public DateTime LastAdminNotification { - get { return _lastAdminNotification; } - set { - _lastAdminNotification = value; - Serialize(); - } - } - - [XmlElement("LastGraceNotification", DataType = "dateTime")] - public DateTime LastGraceNotification { - get { return _lastGraceNotification; } - set { - _lastGraceNotification = value; - Serialize(); - } - } - - public string LimitReason { - get { return _limitReason; } - set { - _limitReason = value; - log("LimitReason was updated (" + value + "), calling Serialize()..."); - Serialize(); - } - } - - public string CurrentTransferSrc { - get { return _currentTransferSrc; } - set { - _currentTransferSrc = value; - log("CurrentTransferSrc was updated (" + value + "), calling Serialize()..."); - Serialize(); - } - } - - public string CurrentTargetTmp { - get { return _currentTargetTmp; } - set { - _currentTargetTmp = value; - log("CurrentTargetTmp was updated (" + value + "), calling Serialize()..."); - Serialize(); - } - } - - public bool ServiceSuspended { - get { return _serviceSuspended; } - set { - _serviceSuspended = value; - log("ServiceSuspended was updated (" + value + "), calling Serialize()..."); - Serialize(); - } - } - - public bool TransferInProgress { - get { return _transferInProgress; } - set { - _transferInProgress = value; - log("FilecopyFinished was updated (" + value + "), calling Serialize()..."); - Serialize(); - } - } - - /// <summary> - /// Indicates whether the service was cleanly shut down (false while the service is running). - /// </summary> - public bool CleanShutdown { - get { return _cleanShutdown; } - set { - _cleanShutdown = value; - Serialize(); - } - } - - public long CurrentTransferSize { - get { return _currentTransferSize; } - set { - _currentTransferSize = value; - log("CurrentTransferSize was updated (" + value + "), calling Serialize()..."); - Serialize(); - } - } - - public ServiceStatus() { - _currentTransferSrc = ""; - _currentTargetTmp = ""; - _transferInProgress = false; - } - - public void Serialize() { - /* During de-serialization, the setter methods get called as well but - * we should not serialize until the deserialization has completed. - * As the storage file name will only be set after this, it is sufficient - * to test for this (plus, we can't serialize anyway without it). - */ - if (_storageFile == null) { - log("File name for XML serialization is not set, doing nothing."); - return; - } - // update the timestamp: - LastStatusUpdate = DateTime.Now; - try { - var xs = new XmlSerializer(GetType()); - var writer = File.CreateText(_storageFile); - xs.Serialize(writer, this); - writer.Flush(); - writer.Close(); - } - catch (Exception ex) { - log("Error in Serialize(): " + ex.Message); - } - log("Finished serializing " + _storageFile); - } - - static void log(string message) { - // use Console.WriteLine until proper logging is there (running as a system - // service means those messages will disappear): - Console.WriteLine(message); - /* - using (var sw = File.AppendText(@"C:\Tools\AutoTx\console.log")) { - sw.WriteLine(message); - } - */ - } - - public static ServiceStatus Deserialize(string file, ServiceConfig config) { - ServiceStatus status; - - var xs = new XmlSerializer(typeof(ServiceStatus)); - try { - var reader = File.OpenText(file); - status = (ServiceStatus) xs.Deserialize(reader); - reader.Close(); - } - catch (Exception) { - // if reading the status XML fails, we return an empty (new) one - status = new ServiceStatus(); - } - status._config = config; - ValidateStatus(status); - // now set the storage filename: - status._storageFile = file; - return status; - } - - private static void ValidateStatus(ServiceStatus s) { - // CurrentTransferSrc - if (s.CurrentTransferSrc.Length > 0 - && !Directory.Exists(s.CurrentTransferSrc)) { - s.ValidationWarnings += " - found non-existing source path of an unfinished " + - "transfer: " + s.CurrentTransferSrc + "\n"; - s.CurrentTransferSrc = ""; - } - - // CurrentTargetTmp - var currentTargetTmpPath = Path.Combine(s._config.DestinationDirectory, - s._config.TmpTransferDir, - s.CurrentTargetTmp); - if (s.CurrentTargetTmp.Length > 0 - && !Directory.Exists(currentTargetTmpPath)) { - s.ValidationWarnings += " - found non-existing temporary path of an " + - "unfinished transfer: " + currentTargetTmpPath+ "\n"; - s.CurrentTargetTmp = ""; - } - - } - - public string Summary() { - return - "CurrentTransferSrc: " + CurrentTransferSrc + "\n" + - "CurrentTargetTmp: " + CurrentTargetTmp + "\n" + - "TransferInProgress: " + TransferInProgress + "\n" + - "CurrentTransferSize: " + CurrentTransferSize + "\n" + - "LastStatusUpdate: " + - LastStatusUpdate.ToString("yyyy-MM-dd HH:mm:ss") + "\n" + - "LastStorageNotification: " + - LastStorageNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n" + - "LastAdminNotification: " + - LastAdminNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n" + - "LastGraceNotification: " + - LastGraceNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n"; - } - } -}