Clean up styles

pull/353/head
NextTurn 2018-12-07 00:00:00 +08:00
parent 6e9d25a7b5
commit 9808ae88e8
No known key found for this signature in database
GPG Key ID: 17A0D50ADDE1A0C4
41 changed files with 765 additions and 824 deletions

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using winsw.Logging;
using System.Diagnostics;
namespace winsw.Logging
{

View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Management;
using System.Reflection;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
@ -12,15 +12,13 @@ using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using Microsoft.Win32;
using winsw.Extensions;
using winsw.Logging;
using winsw.Native;
using winsw.Util;
using WMI;
using ServiceType = WMI.ServiceType;
using winsw.Native;
using System.Reflection;
using winsw.Logging;
namespace winsw
{
@ -32,7 +30,7 @@ namespace winsw
private readonly ServiceDescriptor _descriptor;
private Dictionary<string, string> _envs;
internal WinSWExtensionManager ExtensionManager { private set; get; }
internal WinSWExtensionManager ExtensionManager { get; private set; }
private static readonly ILog Log = LogManager.GetLogger("WinSW");
private static readonly WrapperServiceEventLogProvider eventLogProvider = new WrapperServiceEventLogProvider();
@ -50,17 +48,12 @@ namespace winsw
/// <remarks>
/// The version will be taken from <see cref="AssemblyInfo"/>
/// </remarks>
public static Version Version
{
get { return Assembly.GetExecutingAssembly().GetName().Version; }
}
public static Version Version => Assembly.GetExecutingAssembly().GetName().Version;
/// <summary>
/// Indicates that the system is shutting down.
/// </summary>
public bool IsShuttingDown {
get { return _systemShuttingdown; }
}
public bool IsShuttingDown => _systemShuttingdown;
public WrapperService(ServiceDescriptor descriptor)
{
@ -114,7 +107,6 @@ namespace winsw
{
File.Delete(file);
}
}
/// <summary>
@ -199,7 +191,6 @@ namespace winsw
{
LogEvent("envar " + key + '=' + _envs[key]);
}*/
HandleFileCopies();
// handle downloads
@ -217,6 +208,7 @@ namespace winsw
string errorMessage = "Failed to download " + d.From + " to " + d.To;
LogEvent(errorMessage + ". " + e.Message);
Log.Error(errorMessage, e);
// TODO: move this code into the download logic
if (d.FailOnError)
{
@ -386,7 +378,6 @@ namespace winsw
effectiveWaitHint = (int)_descriptor.WaitHint.TotalMilliseconds;
}
IntPtr handle = ServiceHandle;
_wrapperServiceStatus.checkPoint++;
_wrapperServiceStatus.waitHint = effectiveWaitHint;
@ -406,9 +397,8 @@ namespace winsw
private void StartProcess(Process processToStart, string arguments, String executable, LogHandler logHandler, bool redirectStdin)
{
// Define handler of the completed process
ProcessCompletionCallback processCompletionCallback = delegate(Process proc)
ProcessCompletionCallback processCompletionCallback = proc =>
{
string msg = processToStart.Id + " - " + processToStart.StartInfo.FileName + " " + processToStart.StartInfo.Arguments;
try
@ -425,6 +415,7 @@ namespace winsw
// restart the service automatically
if (proc.ExitCode == 0)
SignalShutdownComplete();
Environment.Exit(proc.ExitCode);
}
}
@ -485,7 +476,6 @@ namespace winsw
throw new WmiException(ReturnValue.NoSuchService);
}
// ReSharper disable once InconsistentNaming
/// <summary>
/// Runs the wrapper.
@ -498,7 +488,6 @@ namespace winsw
{
bool isCLIMode = _args.Length > 0;
// If descriptor is not specified, initialize the new one (and load configs from there)
var d = descriptor ?? new ServiceDescriptor();
@ -506,7 +495,6 @@ namespace winsw
// STDIN and STDOUT of the child process will be handled independently.
InitLoggers(d, isCLIMode);
if (isCLIMode) // CLI mode, in-service mode otherwise
{
Log.Debug("Starting ServiceWrapper in the CLI mode");
@ -629,8 +617,10 @@ namespace winsw
}
}
}
return;
}
if (args[0] == "uninstall")
{
Log.Info("Uninstalling the service with id '" + d.Id + "'");
@ -639,6 +629,7 @@ namespace winsw
Log.Warn("The service with id '" + d.Id + "' does not exist. Nothing to uninstall");
return; // there's no such service, so consider it already uninstalled
}
if (s.Started)
{
// We could fail the opeartion here, but it would be an incompatible change.
@ -664,24 +655,33 @@ namespace winsw
{
Log.Fatal("Failed to uninstall the service with id '" + d.Id + "'. WMI Error code is '" + e.ErrorCode + "'");
}
throw e;
}
return;
}
if (args[0] == "start")
{
Log.Info("Starting the service with id '" + d.Id + "'");
if (s == null) ThrowNoSuchService();
if (s == null)
ThrowNoSuchService();
s.StartService();
return;
}
if (args[0] == "stop")
{
Log.Info("Stopping the service with id '" + d.Id + "'");
if (s == null) ThrowNoSuchService();
if (s == null)
ThrowNoSuchService();
s.StopService();
return;
}
if (args[0] == "restart")
{
Log.Info("Restarting the service with id '" + d.Id + "'");
@ -700,22 +700,24 @@ namespace winsw
s.StartService();
return;
}
if (args[0] == "restart!")
{
Log.Info("Restarting the service with id '" + d.Id + "'");
// run restart from another process group. see README.md for why this is useful.
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
STARTUPINFO si = default;
bool result = Kernel32.CreateProcess(null, d.ExecutablePath+" restart", IntPtr.Zero, IntPtr.Zero, false, 0x200/*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out pi);
bool result = Kernel32.CreateProcess(null, d.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200/*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out PROCESS_INFORMATION pi);
if (!result)
{
throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
}
return;
}
if (args[0] == "status")
{
Log.Debug("User requested the status of the process with id '" + d.Id + "'");
@ -727,6 +729,7 @@ namespace winsw
Console.WriteLine("Stopped");
return;
}
if (args[0] == "test")
{
WrapperService wsvc = new WrapperService(d);
@ -735,6 +738,7 @@ namespace winsw
wsvc.OnStop();
return;
}
if (args[0] == "testwait")
{
WrapperService wsvc = new WrapperService(d);
@ -744,12 +748,14 @@ namespace winsw
wsvc.OnStop();
return;
}
if (args[0] == "help" || args[0] == "--help" || args[0] == "-h"
|| args[0] == "-?" || args[0] == "/?")
{
printHelp();
return;
}
if (args[0] == "version")
{
printVersion();
@ -759,12 +765,12 @@ namespace winsw
Console.WriteLine("Unknown command: " + args[0]);
printAvailableCommandsInfo();
throw new Exception("Unknown command: " + args[0]);
}
else
{
Log.Info("Starting ServiceWrapper in the service mode");
}
Run(new WrapperService(d));
}
@ -851,15 +857,15 @@ namespace winsw
private static void printHelp()
{
Console.WriteLine("A wrapper binary that can be used to host executables as Windows services");
Console.WriteLine("");
Console.WriteLine();
Console.WriteLine("Usage: winsw [/redirect file] <command> [<args>]");
Console.WriteLine(" Missing arguments trigger the service mode");
Console.WriteLine("");
Console.WriteLine();
printAvailableCommandsInfo();
Console.WriteLine("");
Console.WriteLine();
Console.WriteLine("Extra options:");
Console.WriteLine("- '/redirect' - redirect the wrapper's STDOUT and STDERR to the specified file");
Console.WriteLine("");
Console.WriteLine();
printVersion();
Console.WriteLine("More info: https://github.com/kohsuke/winsw");
Console.WriteLine("Bug tracker: https://github.com/kohsuke/winsw/issues");

View File

@ -16,6 +16,7 @@ namespace winsw
[DllImport(KERNEL32)]
private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);
// Delegate type to be used as the Handler Routine for SCCH
private delegate Boolean ConsoleCtrlDelegate(CtrlTypes CtrlType);

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using WMI;
@ -14,11 +13,11 @@ namespace winsw.Configuration
/// </summary>
public sealed class DefaultWinSWSettings : IWinSWConfiguration
{
public string Id { get { return null; } }
public string Caption { get { return null; } }
public string Description { get { return null; } }
public string Executable { get { return null; } }
public bool HideWindow { get { return false; } }
public string Id => null;
public string Caption => null;
public string Description => null;
public string Executable => null;
public bool HideWindow => false;
public string ExecutablePath
{
@ -32,47 +31,47 @@ namespace winsw.Configuration
}
// Installation
public bool AllowServiceAcountLogonRight { get { return false; } }
public string ServiceAccountPassword { get { return null; } }
public string ServiceAccountUser { get { return "NULL\\NULL"; } }
public List<winsw.Native.SC_ACTION> FailureActions { get { return new List<winsw.Native.SC_ACTION>(); } }
public TimeSpan ResetFailureAfter { get { return TimeSpan.FromDays(1); } }
public bool AllowServiceAcountLogonRight => false;
public string ServiceAccountPassword => null;
public string ServiceAccountUser => "NULL\\NULL";
public List<Native.SC_ACTION> FailureActions => new List<Native.SC_ACTION>();
public TimeSpan ResetFailureAfter => TimeSpan.FromDays(1);
// Executable management
public string Arguments { get { return ""; } }
public string Startarguments { get { return null; } }
public string StopExecutable { get { return null; } }
public string Stoparguments { get { return null; } }
public string WorkingDirectory { get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } }
public ProcessPriorityClass Priority { get { return ProcessPriorityClass.Normal; } }
public TimeSpan StopTimeout { get { return TimeSpan.FromSeconds(15); } }
public bool StopParentProcessFirst { get { return false; } }
public string Arguments => string.Empty;
public string Startarguments => null;
public string StopExecutable => null;
public string Stoparguments => null;
public string WorkingDirectory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
public ProcessPriorityClass Priority => ProcessPriorityClass.Normal;
public TimeSpan StopTimeout => TimeSpan.FromSeconds(15);
public bool StopParentProcessFirst => false;
// Service management
public StartMode StartMode { get { return StartMode.Automatic; } }
public bool DelayedAutoStart { get { return false; } }
public string[] ServiceDependencies { get { return new string[0]; } }
public TimeSpan WaitHint { get { return TimeSpan.FromSeconds(15); } }
public TimeSpan SleepTime { get { return TimeSpan.FromSeconds(1); } }
public bool Interactive { get { return false; } }
public StartMode StartMode => StartMode.Automatic;
public bool DelayedAutoStart => false;
public string[] ServiceDependencies => new string[0];
public TimeSpan WaitHint => TimeSpan.FromSeconds(15);
public TimeSpan SleepTime => TimeSpan.FromSeconds(1);
public bool Interactive => false;
// Logging
public string LogDirectory { get { return Path.GetDirectoryName(ExecutablePath); } }
public string LogMode { get { return "append"; } }
public string LogDirectory => Path.GetDirectoryName(ExecutablePath);
public string LogMode => "append";
public bool OutFileDisabled { get { return false; } }
public bool ErrFileDisabled { get { return false; } }
public string OutFilePattern { get { return ".out.log"; } }
public string ErrFilePattern { get { return ".err.log"; } }
public bool OutFileDisabled => false;
public bool ErrFileDisabled => false;
public string OutFilePattern => ".out.log";
public string ErrFilePattern => ".err.log";
// Environment
public List<Download> Downloads { get { return new List<Download>(); } }
public Dictionary<string, string> EnvironmentVariables { get { return new Dictionary<string, string>(); } }
public List<Download> Downloads => new List<Download>();
public Dictionary<string, string> EnvironmentVariables => new Dictionary<string, string>();
// Misc
public bool BeepOnShutdown { get { return false; } }
public bool BeepOnShutdown => false;
// Extensions
public XmlNode ExtensionsConfiguration { get {return null; } }
public XmlNode ExtensionsConfiguration => null;
}
}

View File

@ -20,7 +20,7 @@ namespace winsw.Configuration
bool AllowServiceAcountLogonRight { get; }
string ServiceAccountPassword { get; }
string ServiceAccountUser { get; }
List<winsw.Native.SC_ACTION> FailureActions { get; }
List<Native.SC_ACTION> FailureActions { get; }
TimeSpan ResetFailureAfter { get; }
// Executable management

View File

@ -13,7 +13,12 @@ namespace winsw
/// </summary>
public class Download
{
public enum AuthType { none = 0, sspi, basic }
public enum AuthType
{
none = 0,
sspi,
basic
}
public readonly string From;
public readonly string To;
@ -23,10 +28,16 @@ namespace winsw
public readonly bool UnsecureAuth;
public readonly bool FailOnError;
public string ShortId { get { return String.Format("(download from {0})", From); } }
public string ShortId => $"(download from {From})";
public Download(string from, string to, bool failOnError = false, AuthType auth = AuthType.none,
string username = null, string password = null, bool unsecureAuth = false)
public Download(
string from,
string to,
bool failOnError = false,
AuthType auth = AuthType.none,
string username = null,
string password = null,
bool unsecureAuth = false)
{
From = from;
To = to;
@ -48,12 +59,12 @@ namespace winsw
To = XmlHelper.SingleAttribute<String>(n, "to");
// All arguments below are optional
FailOnError = XmlHelper.SingleAttribute<bool>(n, "failOnError", false);
FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false);
Auth = XmlHelper.EnumAttribute<AuthType>(n, "auth", AuthType.none);
Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.none);
Username = XmlHelper.SingleAttribute<String>(n, "user", null);
Password = XmlHelper.SingleAttribute<String>(n, "password", null);
UnsecureAuth = XmlHelper.SingleAttribute<bool>(n, "unsecureAuth", false);
UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false);
if (Auth == AuthType.basic)
{
@ -69,6 +80,7 @@ namespace winsw
{
throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + ShortId);
}
if (Password == null)
{
throw new InvalidDataException("Basic Auth is enabled, but password is not specified " + ShortId);
@ -87,7 +99,7 @@ namespace winsw
/// <summary>
/// Downloads the requested file and puts it to the specified target.
/// </summary>
/// <exception cref="System.Net.WebException">
/// <exception cref="WebException">
/// Download failure. FailOnError flag should be processed outside.
/// </exception>
public void Perform()
@ -120,6 +132,7 @@ namespace winsw
// only after we successfully downloaded a file, overwrite the existing one
if (File.Exists(To))
File.Delete(To);
File.Move(To + ".tmp", To);
}
@ -129,9 +142,12 @@ namespace winsw
while (true)
{
int len = i.Read(buf, 0, buf.Length);
if (len <= 0) break;
if (len <= 0)
break;
o.Write(buf, 0, len);
}
i.Close();
o.Close();
}

View File

@ -200,7 +200,6 @@ namespace DynamicProxy
FieldBuilder handlerField = typeBuilder.DefineField(
HANDLER_NAME, handlerType, FieldAttributes.Private);
// build a constructor that takes the delegate object as the only argument
// ConstructorInfo defaultObjConstructor = objType.GetConstructor( new Type[0] );
ConstructorInfo superConstructor = objType.GetConstructor(new Type[0]);
@ -242,12 +241,14 @@ namespace DynamicProxy
private static readonly MethodInfo INVOKE_METHOD = typeof(IProxyInvocationHandler).GetMethod("Invoke");
private static readonly MethodInfo GET_METHODINFO_METHOD = typeof(MetaDataFactory).GetMethod("GetMethod", new Type[] { typeof(string), typeof(int) });
private void GenerateMethod( Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder ) {
private void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
{
MetaDataFactory.Add(interfaceType);
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
PropertyInfo[] props = interfaceType.GetProperties();
for ( int i = 0; i < interfaceMethods.Length; i++ ) {
for (int i = 0; i < interfaceMethods.Length; i++)
{
MethodInfo methodInfo = interfaceMethods[i];
// Get the method parameters since we need to create an array
@ -257,7 +258,8 @@ namespace DynamicProxy
Type[] methodParameters = new Type[numOfParams];
// convert the ParameterInfo objects into Type
for ( int j = 0; j < numOfParams; j++ ) {
for (int j = 0; j < numOfParams; j++)
{
methodParameters[j] = methodParams[j].ParameterType;
}
@ -293,33 +295,45 @@ namespace DynamicProxy
// if we have any parameters, then iterate through and set the values
// of each element to the corresponding arguments
for ( int j = 0; j < numOfParams; j++ ) {
for (int j = 0; j < numOfParams; j++)
{
methodIL.Emit(OpCodes.Dup); // this copies the array
methodIL.Emit(OpCodes.Ldc_I4, j);
methodIL.Emit(OpCodes.Ldarg, j + 1);
if ( methodParameters[j].IsValueType ) {
if (methodParameters[j].IsValueType)
{
methodIL.Emit(OpCodes.Box, methodParameters[j]);
}
methodIL.Emit(OpCodes.Stelem_Ref);
}
// call the Invoke method
methodIL.Emit(OpCodes.Callvirt, INVOKE_METHOD);
if ( methodInfo.ReturnType != typeof(void) ) {
if (methodInfo.ReturnType != typeof(void))
{
// if the return type if a value type, then unbox the return value
// so that we don't get junk.
if ( methodInfo.ReturnType.IsValueType ) {
if (methodInfo.ReturnType.IsValueType)
{
methodIL.Emit(OpCodes.Unbox, methodInfo.ReturnType);
if ( methodInfo.ReturnType.IsEnum ) {
if (methodInfo.ReturnType.IsEnum)
{
methodIL.Emit(OpCodes.Ldind_I4);
} else if ( !methodInfo.ReturnType.IsPrimitive ) {
}
else if (!methodInfo.ReturnType.IsPrimitive)
{
methodIL.Emit(OpCodes.Ldobj, methodInfo.ReturnType);
} else {
}
else
{
methodIL.Emit((OpCode)OpCodeTypeMapper[methodInfo.ReturnType]);
}
}
} else {
}
else
{
// pop the return value that Invoke returned from the stack since
// the method's return type is void.
methodIL.Emit(OpCodes.Pop);
@ -340,7 +354,8 @@ namespace DynamicProxy
// }
// Iterate through the parent interfaces and recursively call this method
foreach ( Type parentType in interfaceType.GetInterfaces() ) {
foreach (Type parentType in interfaceType.GetInterfaces())
{
GenerateMethod(parentType, handlerField, typeBuilder);
}
}

View File

@ -1,12 +1,12 @@
using System;
using System.Xml;
using winsw.Util;
namespace winsw.Extensions
{
public abstract class AbstractWinSWExtension : IWinSWExtension
{
public abstract String DisplayName { get; }
public WinSWExtensionDescriptor Descriptor { get; set; }
public virtual void Configure(ServiceDescriptor descriptor, XmlNode node)

View File

@ -18,12 +18,6 @@ namespace winsw.Extensions
ExtensionId = extensionName;
}
public override string Message
{
get
{
return ExtensionId + ": " + base.Message;
}
}
public override string Message => ExtensionId + ": " + base.Message;
}
}

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace winsw.Extensions
namespace winsw.Extensions
{
/// <summary>
/// This attribute is used to identify extension points within the code

View File

@ -1,6 +1,5 @@
using System;
using System.Xml;
using winsw.Util;
namespace winsw.Extensions
{

View File

@ -1,17 +1,16 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Reflection;
using System.Diagnostics;
using winsw.Util;
using System.Xml;
using log4net;
namespace winsw.Extensions
{
public class WinSWExtensionManager
{
public Dictionary<string, IWinSWExtension> Extensions { private set; get; }
public ServiceDescriptor ServiceDescriptor { private set; get; }
public Dictionary<string, IWinSWExtension> Extensions { get; private set; }
public ServiceDescriptor ServiceDescriptor { get; private set; }
private static readonly ILog Log = LogManager.GetLogger(typeof(WinSWExtensionManager));
@ -103,7 +102,6 @@ namespace winsw.Extensions
// TODO: Implement loading of external extensions. Current version supports internal hack
#region Extension load management
/// Loads extensions according to the configuration file.
/// </summary>
/// <param name="logger">Logger</param>
@ -151,6 +149,7 @@ namespace winsw.Extensions
Log.Fatal("Failed to configure the extension " + id, ex);
throw ex;
}
Extensions.Add(id, extension);
Log.Info("Extension loaded: " + id);
}
@ -158,7 +157,6 @@ namespace winsw.Extensions
{
Log.Warn("Extension is disabled: " + id);
}
}
private IWinSWExtension CreateExtensionInstance(string id, string className)
@ -174,6 +172,7 @@ namespace winsw.Extensions
{
throw new ExtensionException(id, "Class " + className + " does not exist");
}
created = Activator.CreateInstance(t);
}
catch (Exception ex)
@ -181,11 +180,11 @@ namespace winsw.Extensions
throw new ExtensionException(id, "Cannot load the class by name: " + className, ex);
}
var extension = created as IWinSWExtension;
if (extension == null)
if (!(created is IWinSWExtension extension))
{
throw new ExtensionException(id, "The loaded class is not a WinSW extension: " + className + ". Type is " + created.GetType());
}
return extension;
}

View File

@ -2,7 +2,6 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Timers;
using ICSharpCode.SharpZipLib.Zip;
namespace winsw
@ -11,6 +10,7 @@ namespace winsw
public interface EventLogger
{
void LogEvent(string message);
void LogEvent(string message, EventLogEntryType type);
}
@ -25,7 +25,7 @@ namespace winsw
/// <summary>
/// Error and information about logging should be reported here.
/// </summary>
public EventLogger EventLogger { set; get; }
public EventLogger EventLogger { get; set; }
/// <summary>
/// Convenience method to copy stuff from StreamReader to StreamWriter
@ -36,10 +36,13 @@ namespace winsw
while (true)
{
int sz = i.Read(buf, 0, buf.Length);
if (sz == 0) break;
if (sz == 0)
break;
o.Write(buf, 0, sz);
o.Flush();
}
i.Close();
o.Close();
}
@ -66,11 +69,11 @@ namespace winsw
/// </summary>
public abstract class AbstractFileLogAppender : LogHandler
{
protected string BaseLogFileName { private set; get; }
protected bool OutFileDisabled { private set; get; }
protected bool ErrFileDisabled { private set; get; }
protected string OutFilePattern { private set; get; }
protected string ErrFilePattern { private set; get; }
protected string BaseLogFileName { get; private set; }
protected bool OutFileDisabled { get; private set; }
protected bool ErrFileDisabled { get; private set; }
protected string OutFilePattern { get; private set; }
protected string ErrFilePattern { get; private set; }
protected AbstractFileLogAppender(string logDirectory, string baseName, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern)
{
@ -84,9 +87,9 @@ namespace winsw
public abstract class SimpleLogAppender : AbstractFileLogAppender
{
public FileMode FileMode { private set; get; }
public string OutputLogFileName { private set; get; }
public string ErrorLogFileName { private set; get; }
public FileMode FileMode { get; private set; }
public string OutputLogFileName { get; private set; }
public string ErrorLogFileName { get; private set; }
protected SimpleLogAppender(string logDirectory, string baseName, FileMode fileMode, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern)
: base(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern)
@ -98,8 +101,11 @@ namespace winsw
public override void log(Stream outputStream, Stream errorStream)
{
if (!OutFileDisabled) new Thread(delegate() { CopyStream(outputStream, new FileStream(OutputLogFileName, FileMode)); }).Start();
if (!ErrFileDisabled) new Thread(delegate() { CopyStream(errorStream, new FileStream(ErrorLogFileName, FileMode)); }).Start();
if (!OutFileDisabled)
new Thread(() => CopyStream(outputStream, new FileStream(OutputLogFileName, FileMode))).Start();
if (!ErrFileDisabled)
new Thread(() => CopyStream(errorStream, new FileStream(ErrorLogFileName, FileMode))).Start();
}
}
@ -126,8 +132,8 @@ namespace winsw
{
public override void log(Stream outputStream, Stream errorStream)
{
new Thread(delegate() { CopyStream(outputStream, Stream.Null); }).Start();
new Thread(delegate() { CopyStream(errorStream, Stream.Null); }).Start();
new Thread(() => CopyStream(outputStream, Stream.Null)).Start();
new Thread(() => CopyStream(errorStream, Stream.Null)).Start();
}
}
@ -145,8 +151,11 @@ namespace winsw
public override void log(Stream outputStream, Stream errorStream)
{
if (!OutFileDisabled) new Thread(delegate() { CopyStreamWithDateRotation(outputStream, OutFilePattern); }).Start();
if (!ErrFileDisabled) new Thread(delegate() { CopyStreamWithDateRotation(errorStream, ErrFilePattern); }).Start();
if (!OutFileDisabled)
new Thread(() => CopyStreamWithDateRotation(outputStream, OutFilePattern)).Start();
if (!ErrFileDisabled)
new Thread(() => CopyStreamWithDateRotation(errorStream, ErrFilePattern)).Start();
}
/// <summary>
@ -162,16 +171,19 @@ namespace winsw
while (true)
{
int len = data.Read(buf, 0, buf.Length);
if (len == 0) break; // EOF
if (len == 0)
break; // EOF
if (periodicRollingCalendar.shouldRoll)
{// rotate at the line boundary
{
// rotate at the line boundary
int offset = 0;
bool rolled = false;
for (int i = 0; i < len; i++)
{
if (buf[i] == 0x0A)
{// at the line boundary.
{
// at the line boundary.
// time to rotate.
w.Write(buf, offset, i + 1);
w.Close();
@ -189,24 +201,25 @@ namespace winsw
}
if (!rolled)
{// we didn't roll - most likely as we didnt find a line boundary, so we should log what we read and roll anyway.
{
// we didn't roll - most likely as we didnt find a line boundary, so we should log what we read and roll anyway.
w.Write(buf, 0, len);
w.Close();
w = new FileStream(BaseLogFileName + "_" + periodicRollingCalendar.format + ext, FileMode.Create);
}
}
else
{// typical case. write the whole thing into the current file
{
// typical case. write the whole thing into the current file
w.Write(buf, 0, len);
}
w.Flush();
}
data.Close();
w.Close();
}
}
public class SizeBasedRollingLogAppender : AbstractFileLogAppender
@ -220,9 +233,9 @@ namespace winsw
// ReSharper disable once InconsistentNaming
public static int DEFAULT_FILES_TO_KEEP = 8;
public int SizeTheshold { private set; get; }
public int SizeTheshold { get; private set; }
public int FilesToKeep { private set; get; }
public int FilesToKeep { get; private set; }
public SizeBasedRollingLogAppender(string logDirectory, string baseName, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern, int sizeThreshold, int filesToKeep)
: base(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern)
@ -236,8 +249,11 @@ namespace winsw
public override void log(Stream outputStream, Stream errorStream)
{
if (!OutFileDisabled) new Thread(delegate() { CopyStreamWithRotation(outputStream, OutFilePattern); }).Start();
if (!ErrFileDisabled) new Thread(delegate() { CopyStreamWithRotation(errorStream, ErrFilePattern); }).Start();
if (!OutFileDisabled)
new Thread(() => CopyStreamWithRotation(outputStream, OutFilePattern)).Start();
if (!ErrFileDisabled)
new Thread(() => CopyStreamWithRotation(errorStream, ErrFilePattern)).Start();
}
/// <summary>
@ -252,9 +268,12 @@ namespace winsw
while (true)
{
int len = data.Read(buf, 0, buf.Length);
if (len == 0) break; // EOF
if (len == 0)
break; // EOF
if (sz + len < SizeTheshold)
{// typical case. write the whole thing into the current file
{
// typical case. write the whole thing into the current file
w.Write(buf, 0, len);
sz += len;
}
@ -264,8 +283,11 @@ namespace winsw
int s = 0;
for (int i = 0; i < len; i++)
{
if (buf[i] != 0x0A) continue;
if (sz + i < SizeTheshold) continue;
if (buf[i] != 0x0A)
continue;
if (sz + i < SizeTheshold)
continue;
// at the line boundary and exceeded the rotation unit.
// time to rotate.
@ -281,9 +303,11 @@ namespace winsw
string src = BaseLogFileName + "." + (j - 2) + ext;
if (File.Exists(dst))
File.Delete(dst);
if (File.Exists(src))
File.Move(src, dst);
}
File.Move(BaseLogFileName + ext, BaseLogFileName + ".0" + ext);
}
catch (IOException e)
@ -300,6 +324,7 @@ namespace winsw
w.Flush();
}
data.Close();
w.Close();
}
@ -317,8 +342,12 @@ namespace winsw
public override void log(Stream outputStream, Stream errorStream)
{
if (!OutFileDisabled) CopyFile(OutputLogFileName, OutputLogFileName + ".old");
if (!ErrFileDisabled) CopyFile(ErrorLogFileName, ErrorLogFileName + ".old");
if (!OutFileDisabled)
CopyFile(OutputLogFileName, OutputLogFileName + ".old");
if (!ErrFileDisabled)
CopyFile(ErrorLogFileName, ErrorLogFileName + ".old");
base.log(outputStream, errorStream);
}
}
@ -326,11 +355,11 @@ namespace winsw
public class RollingSizeTimeLogAppender : AbstractFileLogAppender
{
public static int BYTES_PER_KB = 1024;
public int SizeTheshold { private set; get; }
public string FilePattern { private set; get; }
public TimeSpan? AutoRollAtTime { private set; get; }
public int? ZipOlderThanNumDays { private set; get; }
public string ZipDateFormat { private set; get; }
public int SizeTheshold { get; private set; }
public string FilePattern { get; private set; }
public TimeSpan? AutoRollAtTime { get; private set; }
public int? ZipOlderThanNumDays { get; private set; }
public string ZipDateFormat { get; private set; }
public RollingSizeTimeLogAppender(string logDirectory, string baseName, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern, int sizeThreshold, string filePattern, TimeSpan? autoRollAtTime, int? zipolderthannumdays, string zipdateformat)
: base(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern)
@ -344,8 +373,11 @@ namespace winsw
public override void log(Stream outputStream, Stream errorStream)
{
if (!OutFileDisabled) new Thread(delegate () { CopyStreamWithRotation(outputStream, OutFilePattern); }).Start();
if (!ErrFileDisabled) new Thread(delegate () { CopyStreamWithRotation(errorStream, ErrFilePattern); }).Start();
if (!OutFileDisabled)
new Thread(() => CopyStreamWithRotation(outputStream, OutFilePattern)).Start();
if (!ErrFileDisabled)
new Thread(() => CopyStreamWithRotation(errorStream, ErrFilePattern)).Start();
}
private void CopyStreamWithRotation(Stream data, string ext)
@ -402,10 +434,13 @@ namespace winsw
};
timer.Start();
}
while (true)
{
var len = data.Read(buf, 0, buf.Length);
if (len == 0) break; // EOF
if (len == 0)
break; // EOF
lock (fileLock)
{
if (sz + len < SizeTheshold)
@ -422,8 +457,11 @@ namespace winsw
int s = 0;
for (int i = 0; i < len; i++)
{
if (buf[i] != 0x0A) continue;
if (sz + i < SizeTheshold) continue;
if (buf[i] != 0x0A)
continue;
if (sz + i < SizeTheshold)
continue;
// at the line boundary and exceeded the rotation unit.
// time to rotate.
@ -450,16 +488,19 @@ namespace winsw
EventLogger.LogEvent(string.Format("Failed to roll size time log: {0}", e.Message));
}
}
w.Flush();
}
}
data.Close();
w.Close();
}
private void ZipFiles(string path, string fileExt, string baseZipfilename)
{
if (ZipOlderThanNumDays == null || !(ZipOlderThanNumDays > 0)) return;
if (ZipOlderThanNumDays == null || !(ZipOlderThanNumDays > 0))
return;
try
{
@ -467,7 +508,8 @@ namespace winsw
foreach (var file in files)
{
var fi = new FileInfo(file);
if (fi.LastWriteTimeUtc >= DateTime.UtcNow.AddDays(-ZipOlderThanNumDays.Value)) continue;
if (fi.LastWriteTimeUtc >= DateTime.UtcNow.AddDays(-ZipOlderThanNumDays.Value))
continue;
// lets archive this bugger
ZipTheFile(file, path, fi.LastWriteTimeUtc.ToString(ZipDateFormat), baseZipfilename);
@ -487,7 +529,6 @@ namespace winsw
bool commited = false;
try
{
if (File.Exists(zipfilename))
{
zipFile = new ZipFile(zipfilename);
@ -543,7 +584,7 @@ namespace winsw
if (nowTime > scheduledTime)
scheduledTime = scheduledTime.AddDays(1);
double tickTime = (double) (scheduledTime - DateTime.Now).TotalMilliseconds;
double tickTime = (scheduledTime - DateTime.Now).TotalMilliseconds;
return tickTime;
}
@ -565,23 +606,28 @@ namespace winsw
var hashIndex = filenameOnly.IndexOf('#');
var lastNumberAsString = filenameOnly.Substring(hashIndex + 1, 4);
// var lastNumberAsString = filenameOnly.Substring(filenameOnly.Length - 4, 4);
int lastNumber = 0;
if (int.TryParse(lastNumberAsString, out lastNumber))
if (int.TryParse(lastNumberAsString, out int lastNumber))
{
if (lastNumber > nextFileNumber)
nextFileNumber = lastNumber;
}
else
{
throw new IOException(string.Format("File {0} does not follow the pattern provided", f));
}
}
catch (Exception e)
{
throw new IOException(string.Format("Failed to process file {0} due to error {1}", f, e.Message), e);
}
}
if (nextFileNumber == 0) throw new IOException("Cannot roll the file because matching pattern not found");
if (nextFileNumber == 0)
throw new IOException("Cannot roll the file because matching pattern not found");
nextFileNumber++;
}
return nextFileNumber;
}
}

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Diagnostics;
namespace winsw.Logging
{

View File

@ -1,9 +1,6 @@
using log4net.Appender;
using System.Diagnostics;
using log4net.Appender;
using log4net.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace winsw.Logging
{
@ -31,6 +28,7 @@ namespace winsw.Logging
{
return EventLogEntryType.Error;
}
if (level.Value >= Level.Warn.Value)
{
return EventLogEntryType.Warning;

View File

@ -28,6 +28,7 @@ namespace winsw.Native
{
throw new Exception(String.Format("Error opening service for modifying. Error returned was: 0x{0:X}", Marshal.GetLastWin32Error()));
}
return new Service(svcHandle);
}
@ -53,8 +54,8 @@ namespace winsw.Native
SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS
{
dwResetPeriod = (int)failureResetPeriod.TotalSeconds,
lpRebootMsg = "",
lpCommand = ""
lpRebootMsg = string.Empty,
lpCommand = string.Empty
};
// delete message
// delete the command to run
@ -155,6 +156,7 @@ namespace winsw.Native
{
return GetLogin(username);
}
return username;
}
@ -164,7 +166,7 @@ namespace winsw.Native
/// <returns>The windows error code returned by LsaAddAccountRights</returns>
private static long SetRight(String accountName, String privilegeName)
{
long winErrorCode = 0; //contains the last error
long winErrorCode; // contains the last error
// pointer an size for the SID
IntPtr sid = IntPtr.Zero;
@ -198,9 +200,8 @@ namespace winsw.Native
}
else
{
// initialize an empty unicode-string
LSA_UNICODE_STRING systemName = new LSA_UNICODE_STRING();
LSA_UNICODE_STRING systemName = default;
// combine all policies
const int access = (int)(
LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN |
@ -218,7 +219,6 @@ namespace winsw.Native
LSA_AccessPolicy.POLICY_VIEW_LOCAL_INFORMATION
);
// initialize a pointer for the policy handle
IntPtr policyHandle = IntPtr.Zero;
// these attributes are not used, but LsaOpenPolicy wants them to exists
LSA_OBJECT_ATTRIBUTES objectAttributes = new LSA_OBJECT_ATTRIBUTES
@ -231,7 +231,7 @@ namespace winsw.Native
};
// get a policy handle
uint resultPolicy = Advapi32.LsaOpenPolicy(ref systemName, ref objectAttributes, access, out policyHandle);
uint resultPolicy = Advapi32.LsaOpenPolicy(ref systemName, ref objectAttributes, access, out IntPtr policyHandle);
winErrorCode = Advapi32.LsaNtStatusToWinError(resultPolicy);
if (winErrorCode != 0)
@ -245,7 +245,7 @@ namespace winsw.Native
// initialize an unicode-string for the privilege name
LSA_UNICODE_STRING[] userRights = new LSA_UNICODE_STRING[1];
userRights[0] = new LSA_UNICODE_STRING();
userRights[0] = default;
userRights[0].Buffer = Marshal.StringToHGlobalUni(privilegeName);
userRights[0].Length = (UInt16)(privilegeName.Length * UnicodeEncoding.CharSize);
userRights[0].MaximumLength = (UInt16)((privilegeName.Length + 1) * UnicodeEncoding.CharSize);
@ -260,6 +260,7 @@ namespace winsw.Native
Advapi32.LsaClose(policyHandle);
}
Advapi32.FreeSid(sid);
}
@ -320,7 +321,6 @@ namespace winsw.Native
[DllImport("advapi32.dll", SetLastError = false)]
internal static extern uint LsaNtStatusToWinError(uint status);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb545671(v=vs.85).aspx
@ -452,7 +452,7 @@ namespace winsw.Native
SERVICE_PAUSE_CONTINUE = 0x00040,
SERVICE_INTERROGATE = 0x00080,
SERVICE_USER_DEFINED_CONTROL = 0x00100,
SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
SERVICE_QUERY_CONFIG |
SERVICE_CHANGE_CONFIG |
SERVICE_QUERY_STATUS |
@ -461,7 +461,7 @@ namespace winsw.Native
SERVICE_STOP |
SERVICE_PAUSE_CONTINUE |
SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL)
SERVICE_USER_DEFINED_CONTROL
}
[Flags]
@ -537,7 +537,6 @@ namespace winsw.Native
SERVICE_PAUSED = 0x00000007,
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms685126(v=vs.85).aspx
[StructLayout(LayoutKind.Sequential)]
public struct SC_ACTION

View File

@ -1,6 +1,6 @@
using Microsoft.Win32.SafeHandles;
using System;
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace winsw.Native
{

View File

@ -29,10 +29,16 @@ namespace winsw
public enum PeriodicityType
{
ERRONEOUS, TOP_OF_MILLISECOND, TOP_OF_SECOND, TOP_OF_MINUTE, TOP_OF_HOUR, TOP_OF_DAY
ERRONEOUS,
TOP_OF_MILLISECOND,
TOP_OF_SECOND,
TOP_OF_MINUTE,
TOP_OF_HOUR,
TOP_OF_DAY
}
private static readonly PeriodicityType[] VALID_ORDERED_LIST = {
private static readonly PeriodicityType[] VALID_ORDERED_LIST =
{
PeriodicityType.TOP_OF_MILLISECOND, PeriodicityType.TOP_OF_SECOND, PeriodicityType.TOP_OF_MINUTE, PeriodicityType.TOP_OF_HOUR, PeriodicityType.TOP_OF_DAY
};
@ -54,6 +60,7 @@ namespace winsw
return i;
}
}
return PeriodicityType.ERRONEOUS;
}
@ -100,17 +107,11 @@ namespace winsw
_nextRoll = nextTriggeringTime(now, _period);
return true;
}
return false;
}
}
public string format
{
get
{
return _currentRoll.ToString(_format);
}
}
public string format => _currentRoll.ToString(_format);
}
}

View File

@ -3,7 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Xml;
using winsw.Configuration;
using winsw.Native;
@ -20,8 +19,7 @@ namespace winsw
// ReSharper disable once InconsistentNaming
protected readonly XmlDocument dom = new XmlDocument();
private static readonly DefaultWinSWSettings defaults = new DefaultWinSWSettings();
public static DefaultWinSWSettings Defaults { get { return defaults; } }
public static DefaultWinSWSettings Defaults { get; } = new DefaultWinSWSettings();
/// <summary>
/// Where did we find the configuration file?
@ -37,14 +35,8 @@ namespace winsw
/// </summary>
public string BaseName { get; set; }
public virtual string ExecutablePath
{
get
{
// Currently there is no opportunity to alter the executable path
return Defaults.ExecutablePath;
}
}
public virtual string ExecutablePath => Defaults.ExecutablePath;
public ServiceDescriptor()
{
@ -53,7 +45,9 @@ namespace winsw
// Get the first parent to go into the recursive loop
string p = ExecutablePath;
string baseName = Path.GetFileNameWithoutExtension(p);
if (baseName.EndsWith(".vshost")) baseName = baseName.Substring(0, baseName.Length - 7);
if (baseName.EndsWith(".vshost"))
baseName = baseName.Substring(0, baseName.Length - 7);
DirectoryInfo d = new DirectoryInfo(Path.GetDirectoryName(p));
while (true)
{
@ -73,11 +67,13 @@ namespace winsw
// register the base directory as environment variable so that future expansions can refer to this.
Environment.SetEnvironmentVariable("BASE", d.FullName);
// ditto for ID
Environment.SetEnvironmentVariable("SERVICE_ID", Id);
// New name
Environment.SetEnvironmentVariable(WinSWSystem.ENVVAR_NAME_EXECUTABLE_PATH, ExecutablePath);
// Also inject system environment variables
Environment.SetEnvironmentVariable(WinSWSystem.ENVVAR_NAME_SERVICE_ID, Id);
}
@ -106,7 +102,9 @@ namespace winsw
private string SingleElement(string tagName, bool optional)
{
var n = dom.SelectSingleNode("//" + tagName);
if (n == null && !optional) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
if (n == null && !optional)
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
return n == null ? null : Environment.ExpandEnvironmentVariables(n.InnerText);
}
@ -147,10 +145,12 @@ namespace winsw
return TimeSpan.FromMilliseconds(int.Parse(v.Substring(0, v.Length - s.Key.Length).Trim()) * s.Value);
}
}
return TimeSpan.FromMilliseconds(int.Parse(v));
}
private static readonly Dictionary<string,long> Suffix = new Dictionary<string,long> {
private static readonly Dictionary<string, long> Suffix = new Dictionary<string, long>
{
{ "ms", 1 },
{ "sec", 1000L },
{ "secs", 1000L },
@ -167,31 +167,14 @@ namespace winsw
/// <summary>
/// Path to the executable.
/// </summary>
public string Executable
{
get
{
return SingleElement("executable");
}
}
public string Executable => SingleElement("executable");
public bool HideWindow
{
get {
return SingleBoolElement("hidewindow", Defaults.HideWindow);
}
}
public bool HideWindow => SingleBoolElement("hidewindow", Defaults.HideWindow);
/// <summary>
/// Optionally specify a different Path to an executable to shutdown the service.
/// </summary>
public string StopExecutable
{
get
{
return SingleElement("stopexecutable", true);
}
}
public string StopExecutable => SingleElement("stopexecutable", true);
/// <summary>
/// Arguments or multiple optional argument elements which overrule the arguments element.
@ -223,28 +206,17 @@ namespace winsw
/// <summary>
/// Multiple optional startargument elements.
/// </summary>
public string Startarguments
{
get
{
return AppendTags("startargument", Defaults.Startarguments);
}
}
public string Startarguments => AppendTags("startargument", Defaults.Startarguments);
/// <summary>
/// Multiple optional stopargument elements.
/// </summary>
public string Stoparguments
public string Stoparguments => AppendTags("stopargument", Defaults.Stoparguments);
public string WorkingDirectory
{
get
{
return AppendTags("stopargument", Defaults.Stoparguments);
}
}
public string WorkingDirectory {
get {
var wd = SingleElement("workingdirectory", true);
return String.IsNullOrEmpty(wd) ? Defaults.WorkingDirectory : wd;
}
@ -257,7 +229,7 @@ namespace winsw
List<string> res = new List<string>();
XmlNode argumentNode = ExtensionsConfiguration;
XmlNodeList extensions = argumentNode != null ? argumentNode.SelectNodes("extension") : null;
XmlNodeList extensions = argumentNode?.SelectNodes("extension");
if (extensions != null)
{
foreach (XmlNode e in extensions)
@ -272,14 +244,7 @@ namespace winsw
}
}
public XmlNode ExtensionsConfiguration
{
get
{
XmlNode argumentNode = dom.SelectSingleNode("//extensions");
return argumentNode;
}
}
public XmlNode ExtensionsConfiguration => dom.SelectSingleNode("//extensions");
/// <summary>
/// Combines the contents of all the elements of the given name,
@ -295,7 +260,7 @@ namespace winsw
}
else
{
string arguments = "";
string arguments = string.Empty;
foreach (XmlElement argument in dom.SelectNodes("//" + tagName))
{
@ -314,6 +279,7 @@ namespace winsw
token = '"' + token + '"';
}
}
arguments += " " + token;
}
@ -365,6 +331,7 @@ namespace winsw
{
mode = Defaults.LogMode;
}
return mode;
}
}
@ -379,18 +346,9 @@ namespace winsw
}
}
public bool OutFileDisabled
{
get { return SingleBoolElement("outfiledisabled", Defaults.OutFileDisabled); }
}
public bool OutFileDisabled => SingleBoolElement("outfiledisabled", Defaults.OutFileDisabled);
public bool ErrFileDisabled
{
get
{
return SingleBoolElement("errfiledisabled", Defaults.ErrFileDisabled);
}
}
public bool ErrFileDisabled => SingleBoolElement("errfiledisabled", Defaults.ErrFileDisabled);
public string OutFilePattern
{
@ -414,7 +372,6 @@ namespace winsw
public LogHandler LogHandler
{
get
{
XmlElement e = (XmlElement)dom.SelectSingleNode("//logmode");
@ -423,6 +380,7 @@ namespace winsw
// this is more modern way, to support nested elements as configuration
e = (XmlElement)dom.SelectSingleNode("//log");
}
int sizeThreshold;
switch (LogMode)
{
@ -444,6 +402,7 @@ namespace winsw
{
throw new InvalidDataException("Time Based rolling policy is specified but no pattern can be found in configuration XML.");
}
var pattern = patternNode.InnerText;
int period = SingleIntElement(e, "period", 1);
return new TimeBasedRollingLogAppender(LogDirectory, LogName, OutFileDisabled, ErrFileDisabled, OutFilePattern, ErrFilePattern, pattern, period);
@ -463,29 +422,29 @@ namespace winsw
{
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but no pattern can be found in configuration XML.");
}
XmlNode autoRollAtTimeNode = e.SelectSingleNode("autoRollAtTime");
TimeSpan? autoRollAtTime = null;
if (autoRollAtTimeNode != null)
{
TimeSpan autoRollAtTimeValue;
// validate it
if (!TimeSpan.TryParse(autoRollAtTimeNode.InnerText, out autoRollAtTimeValue))
if (!TimeSpan.TryParse(autoRollAtTimeNode.InnerText, out TimeSpan autoRollAtTimeValue))
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but autoRollAtTime does not match the TimeSpan format HH:mm:ss found in configuration XML.");
autoRollAtTime = autoRollAtTimeValue;
}
XmlNode zipolderthannumdaysNode = e.SelectSingleNode("zipOlderThanNumDays");
int? zipolderthannumdays = null;
if (zipolderthannumdaysNode != null)
{
int zipolderthannumdaysValue;
// validate it
if (!int.TryParse(zipolderthannumdaysNode.InnerText, out zipolderthannumdaysValue))
if (!int.TryParse(zipolderthannumdaysNode.InnerText, out int zipolderthannumdaysValue))
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML.");
zipolderthannumdays = zipolderthannumdaysValue;
}
XmlNode zipdateformatNode = e.SelectSingleNode("zipDateFormat");
string zipdateformat = null;
string zipdateformat;
if (zipdateformatNode == null)
{
zipdateformat = "yyyyMM";
@ -501,7 +460,6 @@ namespace winsw
throw new InvalidDataException("Undefined logging mode: " + LogMode);
}
}
}
/// <summary>
@ -519,35 +477,19 @@ namespace winsw
{
serviceDependencies.Add(depend.InnerText);
}
return (string[])serviceDependencies.ToArray(typeof(string));
}
return Defaults.ServiceDependencies;
}
}
public string Id
{
get
{
return SingleElement("id");
}
}
public string Id => SingleElement("id");
public string Caption
{
get
{
return SingleElement("name");
}
}
public string Caption => SingleElement("name");
public string Description
{
get
{
return SingleElement("description");
}
}
public string Description => SingleElement("description");
/// <summary>
/// Start mode of the Service
@ -557,7 +499,9 @@ namespace winsw
get
{
var p = SingleElement("startmode", true);
if (p == null) return Defaults.StartMode;
if (p == null)
return Defaults.StartMode;
try
{
return (StartMode)Enum.Parse(typeof(StartMode), p, true);
@ -569,6 +513,7 @@ namespace winsw
{
Console.WriteLine(sm);
}
throw;
}
}
@ -578,64 +523,32 @@ namespace winsw
/// True if the service should be installed with the DelayedAutoStart flag.
/// This setting will be applyed only during the install command and only when the Automatic start mode is configured.
/// </summary>
public bool DelayedAutoStart
{
get
{
return dom.SelectSingleNode("//delayedAutoStart") != null;
}
}
public bool DelayedAutoStart => dom.SelectSingleNode("//delayedAutoStart") != null;
/// <summary>
/// True if the service should beep when finished on shutdown.
/// This doesn't work on some OSes. See http://msdn.microsoft.com/en-us/library/ms679277%28VS.85%29.aspx
/// </summary>
public bool BeepOnShutdown
{
get
{
return dom.SelectSingleNode("//beeponshutdown") != null;
}
}
public bool BeepOnShutdown => dom.SelectSingleNode("//beeponshutdown") != null;
/// <summary>
/// The estimated time required for a pending stop operation (default 15 secs).
/// Before the specified amount of time has elapsed, the service should make its next call to the SetServiceStatus function
/// with either an incremented checkPoint value or a change in currentState. (see http://msdn.microsoft.com/en-us/library/ms685996.aspx)
/// </summary>
public TimeSpan WaitHint
{
get
{
return SingleTimeSpanElement(dom, "waithint", Defaults.WaitHint);
}
}
public TimeSpan WaitHint => SingleTimeSpanElement(dom, "waithint", Defaults.WaitHint);
/// <summary>
/// The time before the service should make its next call to the SetServiceStatus function
/// with an incremented checkPoint value (default 1 sec).
/// Do not wait longer than the wait hint. A good interval is one-tenth of the wait hint but not less than 1 second and not more than 10 seconds.
/// </summary>
public TimeSpan SleepTime
{
get
{
return SingleTimeSpanElement(dom, "sleeptime", Defaults.SleepTime);
}
}
public TimeSpan SleepTime => SingleTimeSpanElement(dom, "sleeptime", Defaults.SleepTime);
/// <summary>
/// True if the service can interact with the desktop.
/// </summary>
public bool Interactive
{
get
{
return dom.SelectSingleNode("//interactive") != null;
}
}
public bool Interactive => dom.SelectSingleNode("//interactive") != null;
/// <summary>
/// Environment variable overrides
@ -653,6 +566,7 @@ namespace winsw
Environment.SetEnvironmentVariable(key, value);
}
return map;
}
}
@ -674,12 +588,12 @@ namespace winsw
List<Download> r = new List<Download>();
foreach (XmlNode n in xmlNodeList)
{
XmlElement el = n as XmlElement;
if (el != null)
if (n is XmlElement el)
{
r.Add(new Download(el));
}
}
return r;
}
}
@ -710,21 +624,17 @@ namespace winsw
default:
throw new Exception("Invalid failure action: " + action);
}
XmlAttribute delay = n.Attributes["delay"];
r.Add(new SC_ACTION(type, delay != null ? ParseTimeSpan(delay.Value) : TimeSpan.Zero));
}
}
return r;
}
}
public TimeSpan ResetFailureAfter
{
get
{
return SingleTimeSpanElement(dom, "resetfailure", Defaults.ResetFailureAfter);
}
}
public TimeSpan ResetFailureAfter => SingleTimeSpanElement(dom, "resetfailure", Defaults.ResetFailureAfter);
protected string GetServiceAccountPart(string subNodeName)
{
@ -740,47 +650,19 @@ namespace winsw
}
return null;
}
protected string AllowServiceLogon
{
get
{
return GetServiceAccountPart("allowservicelogon");
}
}
protected string AllowServiceLogon => GetServiceAccountPart("allowservicelogon");
// ReSharper disable once InconsistentNaming
protected string serviceAccountDomain
{
get
{
return GetServiceAccountPart("domain");
}
}
protected string serviceAccountDomain => GetServiceAccountPart("domain");
// ReSharper disable once InconsistentNaming
protected string serviceAccountName
{
get
{
return GetServiceAccountPart("user");
}
}
protected string serviceAccountName => GetServiceAccountPart("user");
public string ServiceAccountPassword
{
get
{
return GetServiceAccountPart("password");
}
}
public string ServiceAccountPassword => GetServiceAccountPart("password");
public string ServiceAccountUser
{
get { return (serviceAccountDomain ?? "NULL") + @"\" + (serviceAccountName ?? "NULL"); }
}
public string ServiceAccountUser => (serviceAccountDomain ?? "NULL") + @"\" + (serviceAccountName ?? "NULL");
public bool HasServiceAccount()
{
@ -793,12 +675,12 @@ namespace winsw
{
if (AllowServiceLogon != null)
{
bool parsedvalue;
if (Boolean.TryParse(AllowServiceLogon, out parsedvalue))
if (Boolean.TryParse(AllowServiceLogon, out bool parsedvalue))
{
return parsedvalue;
}
}
return false;
}
}
@ -806,24 +688,18 @@ namespace winsw
/// <summary>
/// Time to wait for the service to gracefully shutdown the executable before we forcibly kill it
/// </summary>
public TimeSpan StopTimeout
{
get
{
return SingleTimeSpanElement(dom, "stoptimeout", Defaults.StopTimeout);
}
}
public TimeSpan StopTimeout => SingleTimeSpanElement(dom, "stoptimeout", Defaults.StopTimeout);
public bool StopParentProcessFirst
{
get
{
var value = SingleElement("stopparentprocessfirst", true);
bool result;
if (bool.TryParse(value, out result))
if (bool.TryParse(value, out bool result))
{
return result;
}
return Defaults.StopParentProcessFirst;
}
}
@ -836,7 +712,8 @@ namespace winsw
get
{
var p = SingleElement("priority", true);
if (p == null) return Defaults.Priority;
if (p == null)
return Defaults.Priority;
return (ProcessPriorityClass)Enum.Parse(typeof(ProcessPriorityClass), p, true);
}

View File

@ -1,10 +1,9 @@
using log4net;
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Management;
using System.Text;
using System.Threading;
using log4net;
namespace winsw.Util
{
@ -25,7 +24,8 @@ namespace winsw.Util
{
var childPids = new List<int>();
try {
try
{
var searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
foreach (var mo in searcher.Get())
{
@ -172,7 +172,7 @@ namespace winsw.Util
// monitor the completion of the process
if (callback != null)
{
StartThread(delegate
StartThread(() =>
{
processToStart.WaitForExit();
callback(processToStart);
@ -187,7 +187,7 @@ namespace winsw.Util
/// </summary>
public static void StartThread(ThreadStart main)
{
new Thread(delegate()
new Thread(() =>
{
try
{

View File

@ -1,7 +1,7 @@
using log4net;
using System;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using log4net;
using winsw.Native;
namespace winsw.Util
@ -20,6 +20,7 @@ namespace winsw.Util
[DllImport(KERNEL32)]
private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);
// Delegate type to be used as the Handler Routine for SCCH
private delegate Boolean ConsoleCtrlDelegate(CtrlTypes CtrlType);

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml;
namespace winsw.Util
{
@ -19,7 +17,9 @@ namespace winsw.Util
public static string SingleElement(XmlNode node, string tagName, Boolean optional)
{
var n = node.SelectSingleNode(tagName);
if (n == null && !optional) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
if (n == null && !optional)
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
return n == null ? null : Environment.ExpandEnvironmentVariables(n.InnerText);
}
@ -34,7 +34,9 @@ namespace winsw.Util
public static XmlNode SingleNode(XmlNode node, string tagName, Boolean optional)
{
var n = node.SelectSingleNode(tagName);
if (n == null && !optional) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
if (n == null && !optional)
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
return n;
}
@ -52,7 +54,7 @@ namespace winsw.Util
throw new InvalidDataException("Attribute <" + attributeName + "> is missing in configuration XML");
}
return SingleAttribute<TAttributeType>(node, attributeName, default(TAttributeType));
return SingleAttribute(node, attributeName, default(TAttributeType));
}
/// <summary>
@ -64,7 +66,8 @@ namespace winsw.Util
/// <returns>Attribute value (or default)</returns>
public static TAttributeType SingleAttribute<TAttributeType>(XmlElement node, string attributeName, TAttributeType defaultValue)
{
if (!node.HasAttribute(attributeName)) return defaultValue;
if (!node.HasAttribute(attributeName))
return defaultValue;
string rawValue = node.GetAttribute(attributeName);
string substitutedValue = Environment.ExpandEnvironmentVariables(rawValue);
@ -83,7 +86,8 @@ namespace winsw.Util
/// <exception cref="InvalidDataException">Wrong enum value</exception>
public static TAttributeType EnumAttribute<TAttributeType>(XmlElement node, string attributeName, TAttributeType defaultValue)
{
if (!node.HasAttribute(attributeName)) return defaultValue;
if (!node.HasAttribute(attributeName))
return defaultValue;
string rawValue = node.GetAttribute(attributeName);
string substitutedValue = Environment.ExpandEnvironmentVariables(rawValue);

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace winsw
{

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace winsw
namespace winsw
{
/// <summary>
/// Class, which contains generic information about WinSW runtime.
@ -19,11 +15,11 @@ namespace winsw
/// Variable, which points to the service ID.
/// It may be used to determine runaway processes.
/// </summary>
public static string ENVVAR_NAME_SERVICE_ID { get { return SYSTEM_EVNVVAR_PREFIX + "SERVICE_ID"; } }
public static string ENVVAR_NAME_SERVICE_ID => SYSTEM_EVNVVAR_PREFIX + "SERVICE_ID";
/// <summary>
/// Variable, which specifies path to the executable being launched by WinSW.
/// </summary>
public static string ENVVAR_NAME_EXECUTABLE_PATH { get { return SYSTEM_EVNVVAR_PREFIX + "EXECUTABLE"; } }
public static string ENVVAR_NAME_EXECUTABLE_PATH => SYSTEM_EVNVVAR_PREFIX + "EXECUTABLE";
}
}

View File

@ -63,7 +63,8 @@ namespace WMI
public class WmiClassName : Attribute
{
public readonly string Name;
public WmiClassName(string name) { Name = name; }
public WmiClassName(string name) => Name = name;
}
/// <summary>
@ -141,6 +142,7 @@ namespace WMI
_mo[method.Name.Substring(4)] = args[0];
return null;
}
if (method.Name.StartsWith("get_"))
{
return _mo[method.Name.Substring(4)];
@ -180,7 +182,9 @@ namespace WMI
string query = "SELECT * FROM " + _wmiClass + " WHERE ";
for (int i = 0; i < args.Length; i++)
{
if (i != 0) query += " AND ";
if (i != 0)
query += " AND ";
query += ' ' + Capitalize(methodArgs[i].Name) + " = '" + args[i] + "'";
}

View File

@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using log4net;
using winsw.Extensions;
using winsw.Util;
using log4net;
using System.Collections.Specialized;
using System.Text;
namespace winsw.Plugins.RunawayProcessKiller
{
@ -34,7 +34,7 @@ namespace winsw.Plugins.RunawayProcessKiller
/// </summary>
public bool CheckWinSWEnvironmentVariable { get; private set; }
public override String DisplayName { get { return "Runaway Process Killer"; } }
public override String DisplayName => "Runaway Process Killer";
private String ServiceId { get; set; }
@ -74,17 +74,19 @@ namespace winsw.Plugins.RunawayProcessKiller
{
// Read PID file from the disk
int pid;
if (System.IO.File.Exists(Pidfile)) {
if (File.Exists(Pidfile))
{
string pidstring;
try
{
pidstring = System.IO.File.ReadAllText(Pidfile);
pidstring = File.ReadAllText(Pidfile);
}
catch (Exception ex)
{
Logger.Error("Cannot read PID file from " + Pidfile, ex);
return;
}
try
{
pid = Int32.Parse(pidstring);
@ -108,7 +110,7 @@ namespace winsw.Plugins.RunawayProcessKiller
{
proc = Process.GetProcessById(pid);
}
catch (ArgumentException ex)
catch (ArgumentException)
{
Logger.Debug("No runaway process with PID=" + pid + ". The process has been already stopped.");
return;
@ -129,12 +131,14 @@ namespace winsw.Plugins.RunawayProcessKiller
{
Logger.Warn("The process " + pid + " has no " + expectedEnvVarName + " environment variable defined. "
+ "The process has not been started by WinSW, hence it won't be terminated.");
if (Logger.IsDebugEnabled) {
if (Logger.IsDebugEnabled)
{
// TODO replace by String.Join() in .NET 4
String[] keys = new String[previousProcessEnvVars.Count];
previousProcessEnvVars.Keys.CopyTo(keys, 0);
Logger.DebugFormat("Env vars of the process with PID={0}: {1}", new Object[] { pid, String.Join(",", keys) });
}
return;
}
else
@ -155,11 +159,13 @@ namespace winsw.Plugins.RunawayProcessKiller
StringBuilder bldr = new StringBuilder("Stopping the runaway process (pid=");
bldr.Append(pid);
bldr.Append(") and its children. Environment was ");
if (!CheckWinSWEnvironmentVariable) {
if (!CheckWinSWEnvironmentVariable)
{
bldr.Append("not ");
}
bldr.Append("checked, affiliated service ID: ");
bldr.Append(affiliatedServiceId != null ? affiliatedServiceId : "undefined");
bldr.Append(affiliatedServiceId ?? "undefined");
bldr.Append(", process to kill: ");
bldr.Append(proc);
@ -171,12 +177,12 @@ namespace winsw.Plugins.RunawayProcessKiller
/// Records the started process PID for the future use in OnStart() after the restart.
/// </summary>
/// <param name="process"></param>
public override void OnProcessStarted(System.Diagnostics.Process process)
public override void OnProcessStarted(Process process)
{
Logger.Info("Recording PID of the started process:" + process.Id + ". PID file destination is " + Pidfile);
try
{
System.IO.File.WriteAllText(Pidfile, process.Id.ToString());
File.WriteAllText(Pidfile, process.Id.ToString());
}
catch (Exception ex)
{

View File

@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Diagnostics;
using log4net;
using winsw.Extensions;
using winsw.Util;
using log4net;
namespace winsw.Plugins.SharedDirectoryMapper
{
@ -13,7 +12,7 @@ namespace winsw.Plugins.SharedDirectoryMapper
private readonly SharedDirectoryMappingHelper _mapper = new SharedDirectoryMappingHelper();
private readonly List<SharedDirectoryMapperConfig> _entries = new List<SharedDirectoryMapperConfig>();
public override String DisplayName { get { return "Shared Directory Mapper"; } }
public override String DisplayName => "Shared Directory Mapper";
private static readonly ILog Logger = LogManager.GetLogger(typeof(SharedDirectoryMapper));
@ -34,8 +33,7 @@ namespace winsw.Plugins.SharedDirectoryMapper
{
foreach (XmlNode mapNode in nodes)
{
var mapElement = mapNode as XmlElement;
if (mapElement != null)
if (mapNode is XmlElement mapElement)
{
var config = SharedDirectoryMapperConfig.FromXml(mapElement);
_entries.Add(config);
@ -85,7 +83,8 @@ namespace winsw.Plugins.SharedDirectoryMapper
}
}
private void HandleMappingError(SharedDirectoryMapperConfig config, MapperException ex) {
private void HandleMappingError(SharedDirectoryMapperConfig config, MapperException ex)
{
Logger.Error("Mapping of " + config.Label + " failed. STDOUT: " + ex.Process.StandardOutput.ReadToEnd()
+ " \r\nSTDERR: " + ex.Process.StandardError.ReadToEnd(), ex);
throw new ExtensionException(Descriptor.Id, DisplayName + ": Mapping of " + config.Label + "failed", ex);

View File

@ -1,6 +1,5 @@
using System;
using System.Diagnostics;
using winsw.Util;
namespace winsw.Plugins.SharedDirectoryMapper
{

View File

@ -1,9 +1,6 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.IO;
using System.Xml;
using NUnit.Framework;
using winsw;
using winswTests.Util;
@ -16,11 +13,10 @@ namespace winswTests.Configuration
[TestFixture]
class ExamplesTest
{
[Test]
public void allOptionsConfigShouldDeclareDefaults()
public void AllOptionsConfigShouldDeclareDefaults()
{
ServiceDescriptor d = doLoad("allOptions");
ServiceDescriptor d = DoLoad("allOptions");
Assert.AreEqual("myapp", d.Id);
Assert.AreEqual("MyApp Service (powered by WinSW)", d.Caption);
@ -31,9 +27,9 @@ namespace winswTests.Configuration
}
[Test]
public void minimalConfigShouldDeclareDefaults()
public void MinimalConfigShouldDeclareDefaults()
{
ServiceDescriptor d = doLoad("minimal");
ServiceDescriptor d = DoLoad("minimal");
Assert.AreEqual("myapp", d.Id);
Assert.AreEqual("MyApp Service (powered by WinSW)", d.Caption);
@ -43,13 +39,15 @@ namespace winswTests.Configuration
ServiceDescriptorAssert.AssertAllOptionalPropertiesAreDefault(d);
}
private ServiceDescriptor doLoad(string exampleName) {
private ServiceDescriptor DoLoad(string exampleName)
{
var dir = Directory.GetCurrentDirectory();
string path = Path.GetFullPath(dir + "\\..\\..\\..\\..\\..\\..\\examples\\sample-" + exampleName + ".xml");
if (!File.Exists(path))
{
throw new FileNotFoundException("Cannot find the XML file " + path, path);
}
XmlDocument dom = new XmlDocument();
dom.Load(path);
return new ServiceDescriptor(dom);

View File

@ -1,8 +1,6 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System;
using System.IO;
using System.Text;
using NUnit.Framework;
using winsw;
using winswTests.Util;
@ -22,7 +20,7 @@ namespace winswTests
var sd = ConfigXmlBuilder.create()
.WithDownload(d)
.ToServiceDescriptor(true);
var loaded = getSingleEntry(sd);
var loaded = GetSingleEntry(sd);
// Check default values
Assert.That(loaded.FailOnError, Is.EqualTo(false));
@ -40,7 +38,7 @@ namespace winswTests
var sd = ConfigXmlBuilder.create()
.WithDownload(d)
.ToServiceDescriptor(true);
var loaded = getSingleEntry(sd);
var loaded = GetSingleEntry(sd);
// Check default values
Assert.That(loaded.FailOnError, Is.EqualTo(true));
@ -58,7 +56,7 @@ namespace winswTests
var sd = ConfigXmlBuilder.create()
.WithDownload(d)
.ToServiceDescriptor(true);
var loaded = getSingleEntry(sd);
var loaded = GetSingleEntry(sd);
// Check default values
Assert.That(loaded.FailOnError, Is.EqualTo(false));
@ -77,19 +75,19 @@ namespace winswTests
{
var d = new Download(protocolPrefix + "myServer.com:8080/file.txt", To,
auth: Download.AuthType.basic, username: "aUser", password: "aPassword");
assertInitializationFails(d, "you're sending your credentials in clear text to the server");
AssertInitializationFails(d, "you're sending your credentials in clear text to the server");
}
public void ShouldRejectBasicAuth_without_username()
{
var d = new Download(From, To, auth: Download.AuthType.basic, username: null, password: "aPassword");
assertInitializationFails(d, "Basic Auth is enabled, but username is not specified");
AssertInitializationFails(d, "Basic Auth is enabled, but username is not specified");
}
public void ShouldRejectBasicAuth_without_password()
{
var d = new Download(From, To, auth: Download.AuthType.basic, username: "aUser", password: null);
assertInitializationFails(d, "Basic Auth is enabled, but password is not specified");
AssertInitializationFails(d, "Basic Auth is enabled, but password is not specified");
}
/// <summary>
@ -105,7 +103,7 @@ namespace winswTests
.WithDownload(d)
.ToServiceDescriptor(true);
var loaded = getSingleEntry(sd);
var loaded = GetSingleEntry(sd);
Assert.That(loaded.From, Is.EqualTo(From));
Assert.That(loaded.To, Is.EqualTo(To));
Assert.That(loaded.FailOnError, Is.EqualTo(failOnError), "Unexpected FailOnError value");
@ -121,7 +119,7 @@ namespace winswTests
.WithRawEntry("<download from=\"http://www.nosuchhostexists.foo.myorg/foo.xml\" to=\"%BASE%\\foo.xml\"/>")
.ToServiceDescriptor(true);
var loaded = getSingleEntry(sd);
var loaded = GetSingleEntry(sd);
Assert.That(loaded.FailOnError, Is.False);
}
@ -134,7 +132,7 @@ namespace winswTests
var sd = ConfigXmlBuilder.create()
.WithRawEntry("<download from=\"http://www.nosuchhostexists.foo.myorg/foo.xml\" to=\"%BASE%\\foo.xml\" auth=\"" + authType + "\"/>")
.ToServiceDescriptor(true);
var loaded = getSingleEntry(sd);
var loaded = GetSingleEntry(sd);
Assert.That(loaded.Auth, Is.EqualTo(Download.AuthType.sspi));
}
@ -146,27 +144,28 @@ namespace winswTests
.WithRawEntry("<download from=\"http://www.nosuchhostexists.foo.myorg/foo.xml\" to=\"%BASE%\\foo.xml\" auth=\"digest\"/>")
.ToServiceDescriptor(true);
ExceptionHelper.assertFails("Cannot parse <auth> Enum value from string 'digest'", typeof(InvalidDataException), delegate {
var d = getSingleEntry(sd);
ExceptionHelper.assertFails("Cannot parse <auth> Enum value from string 'digest'", typeof(InvalidDataException), () =>
{
var d = GetSingleEntry(sd);
});
}
private Download getSingleEntry(ServiceDescriptor sd)
private Download GetSingleEntry(ServiceDescriptor sd)
{
var downloads = sd.Downloads.ToArray();
Assert.That(downloads.Length, Is.EqualTo(1), "Service Descriptor is expected to have only one entry");
return downloads[0];
}
private void assertInitializationFails(Download download, String expectedMessagePart = null, Type expectedExceptionType = null)
private void AssertInitializationFails(Download download, String expectedMessagePart = null, Type expectedExceptionType = null)
{
var sd = ConfigXmlBuilder.create()
.WithDownload(download)
.ToServiceDescriptor(true);
ExceptionHelper.assertFails(expectedMessagePart, expectedExceptionType ?? typeof(InvalidDataException), delegate
ExceptionHelper.assertFails(expectedMessagePart, expectedExceptionType ?? typeof(InvalidDataException), () =>
{
var d = getSingleEntry(sd);
var d = GetSingleEntry(sd);
});
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace winswTests.Extensions
{
@ -15,7 +13,7 @@ namespace winswTests.Extensions
/// </summary>
/// <param name="type">Type of the extension</param>
/// <returns>String for Type locator, which includes class and assembly names</returns>
public static String getExtensionClassNameWithAssembly(Type type)
public static String GetExtensionClassNameWithAssembly(Type type)
{
return type.ToString() + ", " + type.Assembly;
}

View File

@ -1,14 +1,13 @@
using winsw;
using NUnit.Framework;
using winsw.Extensions;
using winsw.Plugins.SharedDirectoryMapper;
using winsw.Plugins.RunawayProcessKiller;
using winswTests.Util;
using System.IO;
using System.Diagnostics;
using winsw.Util;
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using NUnit.Framework;
using winsw;
using winsw.Extensions;
using winsw.Plugins.RunawayProcessKiller;
using winsw.Util;
using winswTests.Util;
namespace winswTests.Extensions
{
@ -17,7 +16,7 @@ namespace winswTests.Extensions
{
ServiceDescriptor _testServiceDescriptor;
string testExtension = getExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
string testExtension = GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
[SetUp]
public void SetUp()

View File

@ -1,5 +1,5 @@
using winsw;
using NUnit.Framework;
using NUnit.Framework;
using winsw;
using winsw.Extensions;
using winsw.Plugins.SharedDirectoryMapper;
@ -10,12 +10,11 @@ namespace winswTests.Extensions
{
ServiceDescriptor _testServiceDescriptor;
string testExtension = getExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper));
string testExtension = GetExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper));
[SetUp]
public void SetUp()
{
string seedXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
+ "<service> "
+ " <id>SERVICE_NAME</id> "

View File

@ -7,7 +7,6 @@ namespace winswTests
[TestFixture]
class MainTest
{
[Test]
public void PrintVersion()
{

View File

@ -1,18 +1,16 @@
using System;
using System.Diagnostics;
using System.Diagnostics;
using NUnit.Framework;
using winsw;
namespace winswTests
{
using System;
using WMI;
using winswTests.Util;
using WMI;
[TestFixture]
public class ServiceDescriptorTests
{
private ServiceDescriptor _extendedServiceDescriptor;
private const string ExpectedWorkingDirectory = @"Z:\Path\SubPath";
@ -52,7 +50,7 @@ namespace winswTests
}
[Test]
[ExpectedException(typeof(System.ArgumentException))]
[ExpectedException(typeof(ArgumentException))]
public void IncorrectStartMode()
{
const string SeedXml = "<service>"
@ -105,6 +103,7 @@ namespace winswTests
_extendedServiceDescriptor = ServiceDescriptor.FromXML(SeedXml);
Assert.That(_extendedServiceDescriptor.StartMode, Is.EqualTo(StartMode.Manual));
}
[Test]
public void VerifyWorkingDirectory()
{
@ -315,6 +314,7 @@ namespace winswTests
var serviceDescriptor = ServiceDescriptor.FromXML(seedXml);
Assert.That(serviceDescriptor.AllowServiceAcountLogonRight, Is.EqualTo(false));
}
[Test]
public void VerifyServiceLogonRightOmitted()
{
@ -438,9 +438,11 @@ namespace winswTests
public void DelayedStart_RoundTrip(bool enabled)
{
var bldr = ConfigXmlBuilder.create();
if (enabled) {
if (enabled)
{
bldr = bldr.WithDelayedAutoStart();
}
var sd = bldr.ToServiceDescriptor();
Assert.That(sd.DelayedAutoStart, Is.EqualTo(enabled));
}

View File

@ -22,6 +22,7 @@ namespace winswTests.Util
+ "</workingdirectory>"
+ @"<logpath>C:\winsw\logs</logpath>"
+ "</service>";
private static readonly ServiceDescriptor DefaultServiceDescriptor = ServiceDescriptor.FromXML(SeedXml);
/// <summary>
@ -61,6 +62,7 @@ namespace winswTests.Util
using (swOut = new StringWriter())
using (swErr = new StringWriter())
{
try
{
Console.SetOut(swOut);
@ -85,6 +87,7 @@ namespace winswTests.Util
Console.WriteLine(testEx);
}
}
}
return new CLITestResult(swOut.ToString(), swErr.ToString(), testEx);
}
@ -104,7 +107,7 @@ namespace winswTests.Util
[CanBeNull]
public Exception Exception { get; private set; }
public bool HasException { get { return Exception != null; } }
public bool HasException => Exception != null;
public CLITestResult(String output, String err, Exception exception = null)
{

View File

@ -53,10 +53,12 @@ namespace winswTests.Util
// TODO: The encoding is generally wrong
str.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
}
if (XMLComment != null)
{
str.AppendFormat("<!--{0}-->\n", XMLComment);
}
str.Append("<service>\n");
str.AppendFormat(" <id>{0}</id>\n", Id);
str.AppendFormat(" <name>{0}</name>\n", Name);
@ -76,6 +78,7 @@ namespace winswTests.Util
{
str.Append(xml);
}
str.Append(" </extensions>\n");
}
@ -86,6 +89,7 @@ namespace winswTests.Util
Console.Out.WriteLine("Produced config:");
Console.Out.WriteLine(res);
}
return res;
}
@ -107,7 +111,7 @@ namespace winswTests.Util
public ConfigXmlBuilder WithRunawayProcessKiller(RunawayProcessKillerExtension ext, string extensionId = "killRunawayProcess", bool enabled = true)
{
var fullyQualifiedExtensionName = ExtensionTestBase.getExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
var fullyQualifiedExtensionName = ExtensionTestBase.GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
StringBuilder str = new StringBuilder();
str.AppendFormat(" <extension enabled=\"{0}\" className=\"{1}\" id=\"{2}\">\n", new Object[] { enabled, fullyQualifiedExtensionName, extensionId });
str.AppendFormat(" <pidfile>{0}</pidfile>\n", ext.Pidfile);

View File

@ -1,7 +1,5 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Text;
using System;
using NUnit.Framework;
namespace winswTests.Util
{
@ -28,8 +26,6 @@ namespace winswTests.Util
Assert.Fail("Expected exception " + expectedExceptionType + " to be thrown by the operation");
}
}
public delegate void ExceptionHelperExecutionBody();

View File

@ -1,8 +1,7 @@
using NUnit.Framework;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using NUnit.Framework;
namespace winswTests.Util
{
@ -14,7 +13,7 @@ namespace winswTests.Util
/// <returns>tmp Dir</returns>
public static string CreateTmpDirectory(String testName = null)
{
string tempDirectory = Path.Combine(Path.GetTempPath(), "winswTests_" + (testName ?? "") + Path.GetRandomFileName());
string tempDirectory = Path.Combine(Path.GetTempPath(), "winswTests_" + (testName ?? string.Empty) + Path.GetRandomFileName());
Directory.CreateDirectory(tempDirectory);
Console.Out.WriteLine("Created the temporary directory: {0}", tempDirectory);
return tempDirectory;
@ -29,7 +28,8 @@ namespace winswTests.Util
{
Dictionary<string, string> res = new Dictionary<string, string>();
var lines = File.ReadAllLines(filePath);
foreach(var line in lines) {
foreach (var line in lines)
{
var parsed = line.Split("=".ToCharArray(), 2);
if (parsed.Length == 2)
{
@ -40,6 +40,7 @@ namespace winswTests.Util
Assert.Fail("Wrong line in the parsed Set output file: " + line);
}
}
return res;
}
}

View File

@ -1,14 +1,12 @@
using System;
using System.Diagnostics;
using NUnit.Framework;
using winsw;
using System.IO;
using winsw.Util;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using NUnit.Framework;
using winsw.Util;
namespace winswTests.Util
{
[TestFixture]
class ProcessHelperTest
{
@ -25,7 +23,6 @@ namespace winswTests.Util
String scriptFile = Path.Combine(tmpDir, "printenv.bat");
File.WriteAllText(scriptFile, "set > " + envFile);
Process proc = new Process();
var ps = proc.StartInfo;
ps.FileName = scriptFile;
@ -54,7 +51,7 @@ namespace winswTests.Util
{
var tmpDir = FilesystemTestHelper.CreateTmpDirectory();
String scriptFile = Path.Combine(tmpDir, "print_lots_to_stdout.bat");
var lotsOfStdOut = string.Join("", _Range(1,1000));
var lotsOfStdOut = string.Join(string.Empty, _Range(1, 1000));
File.WriteAllText(scriptFile, string.Format("echo \"{0}\"", lotsOfStdOut));
Process proc = new Process();
@ -76,6 +73,7 @@ namespace winswTests.Util
{
range.Add(i.ToString());
}
return range.ToArray();
}
}

View File

@ -1,8 +1,6 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using NUnit.Framework;
using winsw;
using winsw.Configuration;
@ -37,14 +35,17 @@ namespace winswTests.Util
AssertPropertyIsDefault(d, AllOptionalProperties);
}
private static List<string> AllProperties {
get {
private static List<string> AllProperties
{
get
{
var res = new List<string>();
var properties = typeof(IWinSWConfiguration).GetProperties();
foreach (var prop in properties)
{
res.Add(prop.Name);
}
return res;
}
}
@ -62,6 +63,4 @@ namespace winswTests.Util
}
}
}
}