mirror of https://github.com/winsw/winsw
Reorganize projects
parent
35af3bf78d
commit
bbb3cd578c
|
@ -1,3 +0,0 @@
|
|||
# Release notes
|
||||
|
||||
This content has been moved to the [Releases](https://github.com/winsw/winsw/releases).
|
|
@ -64,8 +64,6 @@ User documentation:
|
|||
* Use-cases:
|
||||
* [Self-restarting services](docs/self-restarting-service.md)
|
||||
* [Deferred file operations](docs/deferred-file-operations.md)
|
||||
* Configuration Management:
|
||||
* [Puppet Forge Module](docs/puppetWinSW.md)
|
||||
|
||||
Developer documentation:
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@ jobs:
|
|||
BuildConfiguration: Release
|
||||
steps:
|
||||
- script: |
|
||||
dotnet build -c $(BuildConfiguration) src\winsw.sln -p:Version=$(BuildVersion)
|
||||
dotnet publish -c $(BuildConfiguration) -f netcoreapp3.1 src\Core\ServiceWrapper\winsw.csproj -p:Version=$(BuildVersion)
|
||||
dotnet publish -c $(BuildConfiguration) -f netcoreapp3.1 -r win-x64 src\Core\ServiceWrapper\winsw.csproj -p:PublishSingleFile=true -p:PublishTrimmed=true -p:Version=$(BuildVersion)
|
||||
dotnet publish -c $(BuildConfiguration) -f netcoreapp3.1 -r win-x86 src\Core\ServiceWrapper\winsw.csproj -p:PublishSingleFile=true -p:PublishTrimmed=true -p:Version=$(BuildVersion)
|
||||
dotnet build -c $(BuildConfiguration) src\WinSW.sln -p:Version=$(BuildVersion)
|
||||
dotnet publish -c $(BuildConfiguration) -f netcoreapp3.1 src\WinSW\WinSW.csproj -p:Version=$(BuildVersion)
|
||||
dotnet publish -c $(BuildConfiguration) -f netcoreapp3.1 -r win-x64 src\WinSW\WinSW.csproj -p:PublishSingleFile=true -p:PublishTrimmed=true -p:Version=$(BuildVersion)
|
||||
dotnet publish -c $(BuildConfiguration) -f netcoreapp3.1 -r win-x86 src\WinSW\WinSW.csproj -p:PublishSingleFile=true -p:PublishTrimmed=true -p:Version=$(BuildVersion)
|
||||
displayName: Build
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Install Nuget
|
||||
|
@ -44,7 +44,7 @@ jobs:
|
|||
packagesToPack: WinSW.nuspec
|
||||
versioningScheme: byEnvVar
|
||||
versionEnvVar: BuildVersion
|
||||
- script: dotnet test -c $(BuildConfiguration) --no-build src\Test\winswTests\winswTests.csproj
|
||||
- script: dotnet test -c $(BuildConfiguration) --no-build src\WinSW.Tests\WinSW.Tests.csproj
|
||||
displayName: Test
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish .NET 4.6.1
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("winswTests")]
|
|
@ -1,3 +0,0 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WindowsService")]
|
|
@ -1,180 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace WinSW.Plugins.RunawayProcessKiller
|
||||
{
|
||||
public partial class RunawayProcessKillerExtension
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
private const string Kernel32 = "kernel32.dll";
|
||||
private const string NTDll = "ntdll.dll";
|
||||
|
||||
[DllImport(Kernel32)]
|
||||
internal static extern int IsWow64Process(IntPtr hProcess, out int Wow64Process);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern int NtQueryInformationProcess(
|
||||
IntPtr ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
out PROCESS_BASIC_INFORMATION32 ProcessInformation,
|
||||
int ProcessInformationLength,
|
||||
IntPtr ReturnLength = default);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern int NtQueryInformationProcess(
|
||||
IntPtr ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
out PROCESS_BASIC_INFORMATION64 ProcessInformation,
|
||||
int ProcessInformationLength,
|
||||
IntPtr ReturnLength = default);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern unsafe int NtReadVirtualMemory(
|
||||
IntPtr ProcessHandle,
|
||||
IntPtr BaseAddress,
|
||||
void* Buffer,
|
||||
IntPtr BufferSize,
|
||||
IntPtr NumberOfBytesRead = default);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern int NtWow64QueryInformationProcess64(
|
||||
IntPtr ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
out PROCESS_BASIC_INFORMATION64 ProcessInformation,
|
||||
int ProcessInformationLength,
|
||||
IntPtr ReturnLength = default);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern unsafe int NtWow64ReadVirtualMemory64(
|
||||
IntPtr ProcessHandle,
|
||||
long BaseAddress,
|
||||
void* Buffer,
|
||||
long BufferSize,
|
||||
long NumberOfBytesRead = default);
|
||||
|
||||
internal enum PROCESSINFOCLASS
|
||||
{
|
||||
ProcessBasicInformation = 0,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct MEMORY_BASIC_INFORMATION
|
||||
{
|
||||
public readonly IntPtr BaseAddress;
|
||||
private readonly IntPtr AllocationBase;
|
||||
private readonly uint AllocationProtect;
|
||||
public readonly IntPtr RegionSize;
|
||||
private readonly uint State;
|
||||
private readonly uint Protect;
|
||||
private readonly uint Type;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct PROCESS_BASIC_INFORMATION32
|
||||
{
|
||||
private readonly int Reserved1;
|
||||
public readonly int PebBaseAddress;
|
||||
private fixed int Reserved2[2];
|
||||
private readonly uint UniqueProcessId;
|
||||
private readonly int Reserved3;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct PROCESS_BASIC_INFORMATION64
|
||||
{
|
||||
private readonly long Reserved1;
|
||||
public readonly long PebBaseAddress;
|
||||
private fixed long Reserved2[2];
|
||||
private readonly ulong UniqueProcessId;
|
||||
private readonly long Reserved3;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct PEB32
|
||||
{
|
||||
private fixed byte Reserved1[2];
|
||||
private readonly byte BeingDebugged;
|
||||
private fixed byte Reserved2[1];
|
||||
private fixed int Reserved3[2];
|
||||
private readonly int Ldr;
|
||||
public readonly int ProcessParameters;
|
||||
private fixed int Reserved4[3];
|
||||
private readonly int AtlThunkSListPtr;
|
||||
private readonly int Reserved5;
|
||||
private readonly uint Reserved6;
|
||||
private readonly int Reserved7;
|
||||
private readonly uint Reserved8;
|
||||
private readonly uint AtlThunkSListPtr32;
|
||||
private fixed int Reserved9[45];
|
||||
private fixed byte Reserved10[96];
|
||||
private readonly int PostProcessInitRoutine;
|
||||
private fixed byte Reserved11[128];
|
||||
private fixed int Reserved12[1];
|
||||
private readonly uint SessionId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct PEB64
|
||||
{
|
||||
private fixed byte Reserved1[2];
|
||||
private readonly byte BeingDebugged;
|
||||
private fixed byte Reserved2[1];
|
||||
private fixed long Reserved3[2];
|
||||
private readonly long Ldr;
|
||||
public readonly long ProcessParameters;
|
||||
private fixed long Reserved4[3];
|
||||
private readonly long AtlThunkSListPtr;
|
||||
private readonly long Reserved5;
|
||||
private readonly uint Reserved6;
|
||||
private readonly long Reserved7;
|
||||
private readonly uint Reserved8;
|
||||
private readonly uint AtlThunkSListPtr32;
|
||||
private fixed long Reserved9[45];
|
||||
private fixed byte Reserved10[96];
|
||||
private readonly long PostProcessInitRoutine;
|
||||
private fixed byte Reserved11[128];
|
||||
private fixed long Reserved12[1];
|
||||
private readonly uint SessionId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct RTL_USER_PROCESS_PARAMETERS32
|
||||
{
|
||||
private fixed byte Reserved1[16];
|
||||
private fixed int Reserved2[10];
|
||||
private readonly UNICODE_STRING32 ImagePathName;
|
||||
private readonly UNICODE_STRING32 CommandLine;
|
||||
|
||||
internal readonly int Environment;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct RTL_USER_PROCESS_PARAMETERS64
|
||||
{
|
||||
private fixed byte Reserved1[16];
|
||||
private fixed long Reserved2[10];
|
||||
private readonly UNICODE_STRING64 ImagePathName;
|
||||
private readonly UNICODE_STRING64 CommandLine;
|
||||
|
||||
internal readonly long Environment;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct UNICODE_STRING32
|
||||
{
|
||||
private readonly ushort Length;
|
||||
private readonly ushort MaximumLength;
|
||||
private readonly int Buffer;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct UNICODE_STRING64
|
||||
{
|
||||
private readonly ushort Length;
|
||||
private readonly ushort MaximumLength;
|
||||
private readonly long Buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace WinSW.Plugins.SharedDirectoryMapper
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
internal const uint RESOURCETYPE_DISK = 0x00000001;
|
||||
|
||||
private const string MprLibraryName = "mpr.dll";
|
||||
|
||||
[DllImport(MprLibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WNetAddConnection2W")]
|
||||
internal static extern int WNetAddConnection2(in NETRESOURCE netResource, string? password = null, string? userName = null, uint flags = 0);
|
||||
|
||||
[DllImport(MprLibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WNetCancelConnection2W")]
|
||||
internal static extern int WNetCancelConnection2(string name, uint flags = 0, bool force = false);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct NETRESOURCE
|
||||
{
|
||||
public uint Scope;
|
||||
public uint Type;
|
||||
public uint DisplayType;
|
||||
public uint Usage;
|
||||
public string LocalName;
|
||||
public string RemoteName;
|
||||
public string Comment;
|
||||
public string Provider;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp3.1</TargetFrameworks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<RootNamespace>winsw.Plugins.SharedDirectoryMapper</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\WinSWCore\WinSWCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,3 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WinSW")]
|
|
@ -1,229 +1,229 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using WinSW.Util;
|
||||
|
||||
namespace WinSW
|
||||
{
|
||||
/// <summary>
|
||||
/// Specify the download activities prior to the launch.
|
||||
/// This enables self-updating services.
|
||||
/// </summary>
|
||||
public class Download
|
||||
{
|
||||
public enum AuthType
|
||||
{
|
||||
None = 0,
|
||||
Sspi,
|
||||
Basic
|
||||
}
|
||||
|
||||
private static readonly ILog Logger = LogManager.GetLogger(typeof(Download));
|
||||
|
||||
public readonly string From;
|
||||
public readonly string To;
|
||||
public readonly AuthType Auth;
|
||||
public readonly string? Username;
|
||||
public readonly string? Password;
|
||||
public readonly bool UnsecureAuth;
|
||||
public readonly bool FailOnError;
|
||||
public readonly string? Proxy;
|
||||
|
||||
public string ShortId => $"(download from {this.From})";
|
||||
|
||||
#if NET461
|
||||
static Download()
|
||||
{
|
||||
// If your app runs on .NET Framework 4.7 or later versions, but targets an earlier version
|
||||
AppContext.SetSwitch("Switch.System.Net.DontEnableSystemDefaultTlsVersions", false);
|
||||
}
|
||||
#endif
|
||||
|
||||
// internal
|
||||
public Download(
|
||||
string from,
|
||||
string to,
|
||||
bool failOnError = false,
|
||||
AuthType auth = AuthType.None,
|
||||
string? username = null,
|
||||
string? password = null,
|
||||
bool unsecureAuth = false,
|
||||
string? proxy = null)
|
||||
{
|
||||
this.From = from;
|
||||
this.To = to;
|
||||
this.FailOnError = failOnError;
|
||||
this.Proxy = proxy;
|
||||
this.Auth = auth;
|
||||
this.Username = username;
|
||||
this.Password = password;
|
||||
this.UnsecureAuth = unsecureAuth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the download setting sfrom the XML entry
|
||||
/// </summary>
|
||||
/// <param name="n">XML element</param>
|
||||
/// <exception cref="InvalidDataException">The required attribute is missing or the configuration is invalid</exception>
|
||||
internal Download(XmlElement n)
|
||||
{
|
||||
this.From = XmlHelper.SingleAttribute<string>(n, "from");
|
||||
this.To = XmlHelper.SingleAttribute<string>(n, "to");
|
||||
|
||||
// All arguments below are optional
|
||||
this.FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false);
|
||||
this.Proxy = XmlHelper.SingleAttribute<string>(n, "proxy", null);
|
||||
|
||||
this.Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.None);
|
||||
this.Username = XmlHelper.SingleAttribute<string>(n, "user", null);
|
||||
this.Password = XmlHelper.SingleAttribute<string>(n, "password", null);
|
||||
this.UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false);
|
||||
|
||||
if (this.Auth == AuthType.Basic)
|
||||
{
|
||||
// Allow it only for HTTPS or for UnsecureAuth
|
||||
if (!this.From.StartsWith("https:") && !this.UnsecureAuth)
|
||||
{
|
||||
throw new InvalidDataException("Warning: you're sending your credentials in clear text to the server " + this.ShortId +
|
||||
"If you really want this you must enable 'unsecureAuth' in the configuration");
|
||||
}
|
||||
|
||||
// Also fail if there is no user/password
|
||||
if (this.Username is null)
|
||||
{
|
||||
throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + this.ShortId);
|
||||
}
|
||||
|
||||
if (this.Password is null)
|
||||
{
|
||||
throw new InvalidDataException("Basic Auth is enabled, but password is not specified " + this.ShortId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Source: http://stackoverflow.com/questions/2764577/forcing-basic-authentication-in-webrequest
|
||||
private void SetBasicAuthHeader(WebRequest request, string username, string password)
|
||||
{
|
||||
string authInfo = username + ":" + password;
|
||||
authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(authInfo));
|
||||
request.Headers["Authorization"] = "Basic " + authInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Downloads the requested file and puts it to the specified target.
|
||||
/// </summary>
|
||||
/// <exception cref="WebException">
|
||||
/// Download failure. FailOnError flag should be processed outside.
|
||||
/// </exception>
|
||||
public async Task PerformAsync()
|
||||
{
|
||||
WebRequest request = WebRequest.Create(this.From);
|
||||
if (!string.IsNullOrEmpty(this.Proxy))
|
||||
{
|
||||
CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!);
|
||||
if (proxyInformation.Credentials != null)
|
||||
{
|
||||
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Proxy = new WebProxy(proxyInformation.ServerAddress);
|
||||
}
|
||||
}
|
||||
|
||||
switch (this.Auth)
|
||||
{
|
||||
case AuthType.None:
|
||||
// Do nothing
|
||||
break;
|
||||
|
||||
case AuthType.Sspi:
|
||||
request.UseDefaultCredentials = true;
|
||||
request.PreAuthenticate = true;
|
||||
request.Credentials = CredentialCache.DefaultCredentials;
|
||||
break;
|
||||
|
||||
case AuthType.Basic:
|
||||
this.SetBasicAuthHeader(request, this.Username!, this.Password!);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new WebException("Code defect. Unsupported authentication type: " + this.Auth);
|
||||
}
|
||||
|
||||
bool supportsIfModifiedSince = false;
|
||||
if (request is HttpWebRequest httpRequest && File.Exists(this.To))
|
||||
{
|
||||
supportsIfModifiedSince = true;
|
||||
httpRequest.IfModifiedSince = File.GetLastWriteTime(this.To);
|
||||
}
|
||||
|
||||
DateTime lastModified = default;
|
||||
string tmpFilePath = this.To + ".tmp";
|
||||
try
|
||||
{
|
||||
using (WebResponse response = await request.GetResponseAsync())
|
||||
using (Stream responseStream = response.GetResponseStream())
|
||||
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
||||
{
|
||||
if (supportsIfModifiedSince)
|
||||
{
|
||||
lastModified = ((HttpWebResponse)response).LastModified;
|
||||
}
|
||||
|
||||
await responseStream.CopyToAsync(tmpStream);
|
||||
}
|
||||
|
||||
FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To);
|
||||
|
||||
if (supportsIfModifiedSince)
|
||||
{
|
||||
File.SetLastWriteTime(this.To, lastModified);
|
||||
}
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
if (supportsIfModifiedSince && ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified)
|
||||
{
|
||||
Logger.Info($"Skipped downloading unmodified resource '{this.From}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomProxyInformation
|
||||
{
|
||||
public string ServerAddress { get; }
|
||||
|
||||
public NetworkCredential? Credentials { get; }
|
||||
|
||||
public CustomProxyInformation(string proxy)
|
||||
{
|
||||
if (proxy.Contains("@"))
|
||||
{
|
||||
// Extract proxy credentials
|
||||
int credsFrom = proxy.IndexOf("://") + 3;
|
||||
int credsTo = proxy.LastIndexOf("@");
|
||||
string completeCredsStr = proxy.Substring(credsFrom, credsTo - credsFrom);
|
||||
int credsSeparator = completeCredsStr.IndexOf(":");
|
||||
|
||||
string username = completeCredsStr.Substring(0, credsSeparator);
|
||||
string password = completeCredsStr.Substring(credsSeparator + 1);
|
||||
this.Credentials = new NetworkCredential(username, password);
|
||||
this.ServerAddress = proxy.Replace(completeCredsStr + "@", null);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ServerAddress = proxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using WinSW.Util;
|
||||
|
||||
namespace WinSW
|
||||
{
|
||||
/// <summary>
|
||||
/// Specify the download activities prior to the launch.
|
||||
/// This enables self-updating services.
|
||||
/// </summary>
|
||||
public class Download
|
||||
{
|
||||
public enum AuthType
|
||||
{
|
||||
None = 0,
|
||||
Sspi,
|
||||
Basic
|
||||
}
|
||||
|
||||
private static readonly ILog Logger = LogManager.GetLogger(typeof(Download));
|
||||
|
||||
public readonly string From;
|
||||
public readonly string To;
|
||||
public readonly AuthType Auth;
|
||||
public readonly string? Username;
|
||||
public readonly string? Password;
|
||||
public readonly bool UnsecureAuth;
|
||||
public readonly bool FailOnError;
|
||||
public readonly string? Proxy;
|
||||
|
||||
public string ShortId => $"(download from {this.From})";
|
||||
|
||||
#if NET461
|
||||
static Download()
|
||||
{
|
||||
// If your app runs on .NET Framework 4.7 or later versions, but targets an earlier version
|
||||
AppContext.SetSwitch("Switch.System.Net.DontEnableSystemDefaultTlsVersions", false);
|
||||
}
|
||||
#endif
|
||||
|
||||
// internal
|
||||
public Download(
|
||||
string from,
|
||||
string to,
|
||||
bool failOnError = false,
|
||||
AuthType auth = AuthType.None,
|
||||
string? username = null,
|
||||
string? password = null,
|
||||
bool unsecureAuth = false,
|
||||
string? proxy = null)
|
||||
{
|
||||
this.From = from;
|
||||
this.To = to;
|
||||
this.FailOnError = failOnError;
|
||||
this.Proxy = proxy;
|
||||
this.Auth = auth;
|
||||
this.Username = username;
|
||||
this.Password = password;
|
||||
this.UnsecureAuth = unsecureAuth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the download setting sfrom the XML entry
|
||||
/// </summary>
|
||||
/// <param name="n">XML element</param>
|
||||
/// <exception cref="InvalidDataException">The required attribute is missing or the configuration is invalid</exception>
|
||||
internal Download(XmlElement n)
|
||||
{
|
||||
this.From = XmlHelper.SingleAttribute<string>(n, "from");
|
||||
this.To = XmlHelper.SingleAttribute<string>(n, "to");
|
||||
|
||||
// All arguments below are optional
|
||||
this.FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false);
|
||||
this.Proxy = XmlHelper.SingleAttribute<string>(n, "proxy", null);
|
||||
|
||||
this.Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.None);
|
||||
this.Username = XmlHelper.SingleAttribute<string>(n, "user", null);
|
||||
this.Password = XmlHelper.SingleAttribute<string>(n, "password", null);
|
||||
this.UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false);
|
||||
|
||||
if (this.Auth == AuthType.Basic)
|
||||
{
|
||||
// Allow it only for HTTPS or for UnsecureAuth
|
||||
if (!this.From.StartsWith("https:") && !this.UnsecureAuth)
|
||||
{
|
||||
throw new InvalidDataException("Warning: you're sending your credentials in clear text to the server " + this.ShortId +
|
||||
"If you really want this you must enable 'unsecureAuth' in the configuration");
|
||||
}
|
||||
|
||||
// Also fail if there is no user/password
|
||||
if (this.Username is null)
|
||||
{
|
||||
throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + this.ShortId);
|
||||
}
|
||||
|
||||
if (this.Password is null)
|
||||
{
|
||||
throw new InvalidDataException("Basic Auth is enabled, but password is not specified " + this.ShortId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Source: http://stackoverflow.com/questions/2764577/forcing-basic-authentication-in-webrequest
|
||||
private void SetBasicAuthHeader(WebRequest request, string username, string password)
|
||||
{
|
||||
string authInfo = username + ":" + password;
|
||||
authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(authInfo));
|
||||
request.Headers["Authorization"] = "Basic " + authInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Downloads the requested file and puts it to the specified target.
|
||||
/// </summary>
|
||||
/// <exception cref="WebException">
|
||||
/// Download failure. FailOnError flag should be processed outside.
|
||||
/// </exception>
|
||||
public async Task PerformAsync()
|
||||
{
|
||||
WebRequest request = WebRequest.Create(this.From);
|
||||
if (!string.IsNullOrEmpty(this.Proxy))
|
||||
{
|
||||
CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!);
|
||||
if (proxyInformation.Credentials != null)
|
||||
{
|
||||
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Proxy = new WebProxy(proxyInformation.ServerAddress);
|
||||
}
|
||||
}
|
||||
|
||||
switch (this.Auth)
|
||||
{
|
||||
case AuthType.None:
|
||||
// Do nothing
|
||||
break;
|
||||
|
||||
case AuthType.Sspi:
|
||||
request.UseDefaultCredentials = true;
|
||||
request.PreAuthenticate = true;
|
||||
request.Credentials = CredentialCache.DefaultCredentials;
|
||||
break;
|
||||
|
||||
case AuthType.Basic:
|
||||
this.SetBasicAuthHeader(request, this.Username!, this.Password!);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new WebException("Code defect. Unsupported authentication type: " + this.Auth);
|
||||
}
|
||||
|
||||
bool supportsIfModifiedSince = false;
|
||||
if (request is HttpWebRequest httpRequest && File.Exists(this.To))
|
||||
{
|
||||
supportsIfModifiedSince = true;
|
||||
httpRequest.IfModifiedSince = File.GetLastWriteTime(this.To);
|
||||
}
|
||||
|
||||
DateTime lastModified = default;
|
||||
string tmpFilePath = this.To + ".tmp";
|
||||
try
|
||||
{
|
||||
using (WebResponse response = await request.GetResponseAsync())
|
||||
using (Stream responseStream = response.GetResponseStream())
|
||||
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
||||
{
|
||||
if (supportsIfModifiedSince)
|
||||
{
|
||||
lastModified = ((HttpWebResponse)response).LastModified;
|
||||
}
|
||||
|
||||
await responseStream.CopyToAsync(tmpStream);
|
||||
}
|
||||
|
||||
FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To);
|
||||
|
||||
if (supportsIfModifiedSince)
|
||||
{
|
||||
File.SetLastWriteTime(this.To, lastModified);
|
||||
}
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
if (supportsIfModifiedSince && ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified)
|
||||
{
|
||||
Logger.Info($"Skipped downloading unmodified resource '{this.From}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomProxyInformation
|
||||
{
|
||||
public string ServerAddress { get; }
|
||||
|
||||
public NetworkCredential? Credentials { get; }
|
||||
|
||||
public CustomProxyInformation(string proxy)
|
||||
{
|
||||
if (proxy.Contains("@"))
|
||||
{
|
||||
// Extract proxy credentials
|
||||
int credsFrom = proxy.IndexOf("://") + 3;
|
||||
int credsTo = proxy.LastIndexOf("@");
|
||||
string completeCredsStr = proxy.Substring(credsFrom, credsTo - credsFrom);
|
||||
int credsSeparator = completeCredsStr.IndexOf(":");
|
||||
|
||||
string username = completeCredsStr.Substring(0, credsSeparator);
|
||||
string password = completeCredsStr.Substring(credsSeparator + 1);
|
||||
this.Credentials = new NetworkCredential(username, password);
|
||||
this.ServerAddress = proxy.Replace(completeCredsStr + "@", null);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ServerAddress = proxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,108 +1,108 @@
|
|||
using System;
|
||||
|
||||
namespace WinSW
|
||||
{
|
||||
// This is largely borrowed from the logback Rolling Calendar.
|
||||
public class PeriodicRollingCalendar
|
||||
{
|
||||
private readonly string format;
|
||||
private readonly long period;
|
||||
private DateTime currentRoll;
|
||||
private DateTime nextRoll;
|
||||
|
||||
public PeriodicRollingCalendar(string format, long period)
|
||||
{
|
||||
this.format = format;
|
||||
this.period = period;
|
||||
this.currentRoll = DateTime.Now;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
this.Periodicity = this.DeterminePeriodicityType();
|
||||
this.nextRoll = this.NextTriggeringTime(this.currentRoll, this.period);
|
||||
}
|
||||
|
||||
public enum PeriodicityType
|
||||
{
|
||||
ERRONEOUS,
|
||||
TOP_OF_MILLISECOND,
|
||||
TOP_OF_SECOND,
|
||||
TOP_OF_MINUTE,
|
||||
TOP_OF_HOUR,
|
||||
TOP_OF_DAY
|
||||
}
|
||||
|
||||
private static readonly PeriodicityType[] ValidOrderedList =
|
||||
{
|
||||
PeriodicityType.TOP_OF_MILLISECOND, PeriodicityType.TOP_OF_SECOND, PeriodicityType.TOP_OF_MINUTE, PeriodicityType.TOP_OF_HOUR, PeriodicityType.TOP_OF_DAY
|
||||
};
|
||||
|
||||
private PeriodicityType DeterminePeriodicityType()
|
||||
{
|
||||
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
|
||||
DateTime epoch = new DateTime(1970, 1, 1);
|
||||
|
||||
foreach (PeriodicityType i in ValidOrderedList)
|
||||
{
|
||||
string r0 = epoch.ToString(this.format);
|
||||
periodicRollingCalendar.Periodicity = i;
|
||||
|
||||
DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
|
||||
string r1 = next.ToString(this.format);
|
||||
|
||||
if (r0 != r1)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return PeriodicityType.ERRONEOUS;
|
||||
}
|
||||
|
||||
private DateTime NextTriggeringTime(DateTime input, long increment) => this.Periodicity switch
|
||||
{
|
||||
PeriodicityType.TOP_OF_MILLISECOND =>
|
||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond)
|
||||
.AddMilliseconds(increment),
|
||||
|
||||
PeriodicityType.TOP_OF_SECOND =>
|
||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)
|
||||
.AddSeconds(increment),
|
||||
|
||||
PeriodicityType.TOP_OF_MINUTE =>
|
||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)
|
||||
.AddMinutes(increment),
|
||||
|
||||
PeriodicityType.TOP_OF_HOUR =>
|
||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)
|
||||
.AddHours(increment),
|
||||
|
||||
PeriodicityType.TOP_OF_DAY =>
|
||||
new DateTime(input.Year, input.Month, input.Day)
|
||||
.AddDays(increment),
|
||||
|
||||
_ => throw new Exception("invalid periodicity type: " + this.Periodicity),
|
||||
};
|
||||
|
||||
public PeriodicityType Periodicity { get; set; }
|
||||
|
||||
public bool ShouldRoll
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
if (now > this.nextRoll)
|
||||
{
|
||||
this.currentRoll = now;
|
||||
this.nextRoll = this.NextTriggeringTime(now, this.period);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public string Format => this.currentRoll.ToString(this.format);
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace WinSW
|
||||
{
|
||||
// This is largely borrowed from the logback Rolling Calendar.
|
||||
public class PeriodicRollingCalendar
|
||||
{
|
||||
private readonly string format;
|
||||
private readonly long period;
|
||||
private DateTime currentRoll;
|
||||
private DateTime nextRoll;
|
||||
|
||||
public PeriodicRollingCalendar(string format, long period)
|
||||
{
|
||||
this.format = format;
|
||||
this.period = period;
|
||||
this.currentRoll = DateTime.Now;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
this.Periodicity = this.DeterminePeriodicityType();
|
||||
this.nextRoll = this.NextTriggeringTime(this.currentRoll, this.period);
|
||||
}
|
||||
|
||||
public enum PeriodicityType
|
||||
{
|
||||
ERRONEOUS,
|
||||
TOP_OF_MILLISECOND,
|
||||
TOP_OF_SECOND,
|
||||
TOP_OF_MINUTE,
|
||||
TOP_OF_HOUR,
|
||||
TOP_OF_DAY
|
||||
}
|
||||
|
||||
private static readonly PeriodicityType[] ValidOrderedList =
|
||||
{
|
||||
PeriodicityType.TOP_OF_MILLISECOND, PeriodicityType.TOP_OF_SECOND, PeriodicityType.TOP_OF_MINUTE, PeriodicityType.TOP_OF_HOUR, PeriodicityType.TOP_OF_DAY
|
||||
};
|
||||
|
||||
private PeriodicityType DeterminePeriodicityType()
|
||||
{
|
||||
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
|
||||
DateTime epoch = new DateTime(1970, 1, 1);
|
||||
|
||||
foreach (PeriodicityType i in ValidOrderedList)
|
||||
{
|
||||
string r0 = epoch.ToString(this.format);
|
||||
periodicRollingCalendar.Periodicity = i;
|
||||
|
||||
DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
|
||||
string r1 = next.ToString(this.format);
|
||||
|
||||
if (r0 != r1)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return PeriodicityType.ERRONEOUS;
|
||||
}
|
||||
|
||||
private DateTime NextTriggeringTime(DateTime input, long increment) => this.Periodicity switch
|
||||
{
|
||||
PeriodicityType.TOP_OF_MILLISECOND =>
|
||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond)
|
||||
.AddMilliseconds(increment),
|
||||
|
||||
PeriodicityType.TOP_OF_SECOND =>
|
||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)
|
||||
.AddSeconds(increment),
|
||||
|
||||
PeriodicityType.TOP_OF_MINUTE =>
|
||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)
|
||||
.AddMinutes(increment),
|
||||
|
||||
PeriodicityType.TOP_OF_HOUR =>
|
||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)
|
||||
.AddHours(increment),
|
||||
|
||||
PeriodicityType.TOP_OF_DAY =>
|
||||
new DateTime(input.Year, input.Month, input.Day)
|
||||
.AddDays(increment),
|
||||
|
||||
_ => throw new Exception("invalid periodicity type: " + this.Periodicity),
|
||||
};
|
||||
|
||||
public PeriodicityType Periodicity { get; set; }
|
||||
|
||||
public bool ShouldRoll
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
if (now > this.nextRoll)
|
||||
{
|
||||
this.currentRoll = now;
|
||||
this.nextRoll = this.NextTriggeringTime(now, this.period);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public string Format => this.currentRoll.ToString(this.format);
|
||||
}
|
||||
}
|
1460
src/Core/WinSWCore/ServiceDescriptor.cs → src/WinSW.Core/ServiceDescriptor.cs
Executable file → Normal file
1460
src/Core/WinSWCore/ServiceDescriptor.cs → src/WinSW.Core/ServiceDescriptor.cs
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
|
@ -5,8 +5,6 @@
|
|||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
||||
<RootNamespace>winsw</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
|
@ -1,12 +1,13 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using WinSW.Extensions;
|
||||
using WinSW.Util;
|
||||
using static WinSW.Plugins.RunawayProcessKiller.RunawayProcessKillerExtension.NativeMethods;
|
||||
using static WinSW.Plugins.RunawayProcessKiller.RunawayProcessKillerExtension.Native;
|
||||
|
||||
namespace WinSW.Plugins.RunawayProcessKiller
|
||||
{
|
||||
|
@ -287,5 +288,177 @@ namespace WinSW.Plugins.RunawayProcessKiller
|
|||
Logger.Error("Cannot update the PID file " + this.Pidfile, ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Native
|
||||
{
|
||||
private const string Kernel32 = "kernel32.dll";
|
||||
private const string NTDll = "ntdll.dll";
|
||||
|
||||
[DllImport(Kernel32)]
|
||||
internal static extern int IsWow64Process(IntPtr hProcess, out int Wow64Process);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern int NtQueryInformationProcess(
|
||||
IntPtr ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
out PROCESS_BASIC_INFORMATION32 ProcessInformation,
|
||||
int ProcessInformationLength,
|
||||
IntPtr ReturnLength = default);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern int NtQueryInformationProcess(
|
||||
IntPtr ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
out PROCESS_BASIC_INFORMATION64 ProcessInformation,
|
||||
int ProcessInformationLength,
|
||||
IntPtr ReturnLength = default);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern unsafe int NtReadVirtualMemory(
|
||||
IntPtr ProcessHandle,
|
||||
IntPtr BaseAddress,
|
||||
void* Buffer,
|
||||
IntPtr BufferSize,
|
||||
IntPtr NumberOfBytesRead = default);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern int NtWow64QueryInformationProcess64(
|
||||
IntPtr ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
out PROCESS_BASIC_INFORMATION64 ProcessInformation,
|
||||
int ProcessInformationLength,
|
||||
IntPtr ReturnLength = default);
|
||||
|
||||
[DllImport(NTDll)]
|
||||
internal static extern unsafe int NtWow64ReadVirtualMemory64(
|
||||
IntPtr ProcessHandle,
|
||||
long BaseAddress,
|
||||
void* Buffer,
|
||||
long BufferSize,
|
||||
long NumberOfBytesRead = default);
|
||||
|
||||
internal enum PROCESSINFOCLASS
|
||||
{
|
||||
ProcessBasicInformation = 0,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct MEMORY_BASIC_INFORMATION
|
||||
{
|
||||
public readonly IntPtr BaseAddress;
|
||||
private readonly IntPtr AllocationBase;
|
||||
private readonly uint AllocationProtect;
|
||||
public readonly IntPtr RegionSize;
|
||||
private readonly uint State;
|
||||
private readonly uint Protect;
|
||||
private readonly uint Type;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct PROCESS_BASIC_INFORMATION32
|
||||
{
|
||||
private readonly int Reserved1;
|
||||
public readonly int PebBaseAddress;
|
||||
private fixed int Reserved2[2];
|
||||
private readonly uint UniqueProcessId;
|
||||
private readonly int Reserved3;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct PROCESS_BASIC_INFORMATION64
|
||||
{
|
||||
private readonly long Reserved1;
|
||||
public readonly long PebBaseAddress;
|
||||
private fixed long Reserved2[2];
|
||||
private readonly ulong UniqueProcessId;
|
||||
private readonly long Reserved3;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct PEB32
|
||||
{
|
||||
private fixed byte Reserved1[2];
|
||||
private readonly byte BeingDebugged;
|
||||
private fixed byte Reserved2[1];
|
||||
private fixed int Reserved3[2];
|
||||
private readonly int Ldr;
|
||||
public readonly int ProcessParameters;
|
||||
private fixed int Reserved4[3];
|
||||
private readonly int AtlThunkSListPtr;
|
||||
private readonly int Reserved5;
|
||||
private readonly uint Reserved6;
|
||||
private readonly int Reserved7;
|
||||
private readonly uint Reserved8;
|
||||
private readonly uint AtlThunkSListPtr32;
|
||||
private fixed int Reserved9[45];
|
||||
private fixed byte Reserved10[96];
|
||||
private readonly int PostProcessInitRoutine;
|
||||
private fixed byte Reserved11[128];
|
||||
private fixed int Reserved12[1];
|
||||
private readonly uint SessionId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct PEB64
|
||||
{
|
||||
private fixed byte Reserved1[2];
|
||||
private readonly byte BeingDebugged;
|
||||
private fixed byte Reserved2[1];
|
||||
private fixed long Reserved3[2];
|
||||
private readonly long Ldr;
|
||||
public readonly long ProcessParameters;
|
||||
private fixed long Reserved4[3];
|
||||
private readonly long AtlThunkSListPtr;
|
||||
private readonly long Reserved5;
|
||||
private readonly uint Reserved6;
|
||||
private readonly long Reserved7;
|
||||
private readonly uint Reserved8;
|
||||
private readonly uint AtlThunkSListPtr32;
|
||||
private fixed long Reserved9[45];
|
||||
private fixed byte Reserved10[96];
|
||||
private readonly long PostProcessInitRoutine;
|
||||
private fixed byte Reserved11[128];
|
||||
private fixed long Reserved12[1];
|
||||
private readonly uint SessionId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct RTL_USER_PROCESS_PARAMETERS32
|
||||
{
|
||||
private fixed byte Reserved1[16];
|
||||
private fixed int Reserved2[10];
|
||||
private readonly UNICODE_STRING32 ImagePathName;
|
||||
private readonly UNICODE_STRING32 CommandLine;
|
||||
|
||||
internal readonly int Environment;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct RTL_USER_PROCESS_PARAMETERS64
|
||||
{
|
||||
private fixed byte Reserved1[16];
|
||||
private fixed long Reserved2[10];
|
||||
private readonly UNICODE_STRING64 ImagePathName;
|
||||
private readonly UNICODE_STRING64 CommandLine;
|
||||
|
||||
internal readonly long Environment;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct UNICODE_STRING32
|
||||
{
|
||||
private readonly ushort Length;
|
||||
private readonly ushort MaximumLength;
|
||||
private readonly int Buffer;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct UNICODE_STRING64
|
||||
{
|
||||
private readonly ushort Length;
|
||||
private readonly ushort MaximumLength;
|
||||
private readonly long Buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using WinSW.Extensions;
|
||||
using WinSW.Util;
|
||||
using static WinSW.Plugins.SharedDirectoryMapper.NativeMethods;
|
||||
using static WinSW.Plugins.SharedDirectoryMapper.SharedDirectoryMapper.Native;
|
||||
|
||||
namespace WinSW.Plugins.SharedDirectoryMapper
|
||||
{
|
||||
|
@ -91,5 +92,31 @@ namespace WinSW.Plugins.SharedDirectoryMapper
|
|||
Win32Exception inner = new Win32Exception(error);
|
||||
throw new ExtensionException(this.Descriptor.Id, $"{this.DisplayName}: {message} {inner.Message}", inner);
|
||||
}
|
||||
|
||||
internal static class Native
|
||||
{
|
||||
internal const uint RESOURCETYPE_DISK = 0x00000001;
|
||||
|
||||
private const string MprLibraryName = "mpr.dll";
|
||||
|
||||
[DllImport(MprLibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WNetAddConnection2W")]
|
||||
internal static extern int WNetAddConnection2(in NETRESOURCE netResource, string? password = null, string? userName = null, uint flags = 0);
|
||||
|
||||
[DllImport(MprLibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WNetCancelConnection2W")]
|
||||
internal static extern int WNetCancelConnection2(string name, uint flags = 0, bool force = false);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct NETRESOURCE
|
||||
{
|
||||
public uint Scope;
|
||||
public uint Type;
|
||||
public uint DisplayType;
|
||||
public uint Usage;
|
||||
public string LocalName;
|
||||
public string RemoteName;
|
||||
public string Comment;
|
||||
public string Provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,6 @@
|
|||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
||||
<RootNamespace>winsw.Plugins.RunawayProcessKiller</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
|
||||
|
@ -14,7 +12,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\WinSWCore\WinSWCore.csproj" />
|
||||
<ProjectReference Include="..\WinSW.Core\WinSW.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,423 +1,423 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceProcess;
|
||||
using WinSW.Tests.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WinSW.Tests
|
||||
{
|
||||
public class ServiceDescriptorTests
|
||||
{
|
||||
private const string ExpectedWorkingDirectory = @"Z:\Path\SubPath";
|
||||
private const string Username = "User";
|
||||
private const string Password = "Password";
|
||||
private const string Domain = "Domain";
|
||||
private const string AllowServiceAccountLogonRight = "true";
|
||||
|
||||
private ServiceDescriptor extendedServiceDescriptor;
|
||||
|
||||
public ServiceDescriptorTests()
|
||||
{
|
||||
string seedXml =
|
||||
$@"<service>
|
||||
<id>service.exe</id>
|
||||
<name>Service</name>
|
||||
<description>The service.</description>
|
||||
<executable>node.exe</executable>
|
||||
<arguments>My Arguments</arguments>
|
||||
<log mode=""roll""></log>
|
||||
<serviceaccount>
|
||||
<username>{Domain}\{Username}</username>
|
||||
<password>{Password}</password>
|
||||
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||
</serviceaccount>
|
||||
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||
<logpath>C:\logs</logpath>
|
||||
</service>";
|
||||
this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultStartMode()
|
||||
{
|
||||
Assert.Equal(ServiceStartMode.Automatic, this.extendedServiceDescriptor.StartMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncorrectStartMode()
|
||||
{
|
||||
string seedXml =
|
||||
$@"<service>
|
||||
<id>service.exe</id>
|
||||
<name>Service</name>
|
||||
<description>The service.</description>
|
||||
<executable>node.exe</executable>
|
||||
<arguments>My Arguments</arguments>
|
||||
<startmode>roll</startmode>
|
||||
<log mode=""roll""></log>
|
||||
<serviceaccount>
|
||||
<username>{Domain}\{Username}</username>
|
||||
<password>{Password}</password>
|
||||
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||
</serviceaccount>
|
||||
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||
<logpath>C:\logs</logpath>
|
||||
</service>";
|
||||
|
||||
this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
Assert.Throws<ArgumentException>(() => this.extendedServiceDescriptor.StartMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChangedStartMode()
|
||||
{
|
||||
string seedXml =
|
||||
$@"<service>
|
||||
<id>service.exe</id>
|
||||
<name>Service</name>
|
||||
<description>The service.</description>
|
||||
<executable>node.exe</executable>
|
||||
<arguments>My Arguments</arguments>
|
||||
<startmode>manual</startmode>
|
||||
<log mode=""roll""></log>
|
||||
<serviceaccount>
|
||||
<username>{Domain}\{Username}</username>
|
||||
<password>{Password}</password>
|
||||
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||
</serviceaccount>
|
||||
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||
<logpath>C:\logs</logpath>
|
||||
</service>";
|
||||
|
||||
this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
Assert.Equal(ServiceStartMode.Manual, this.extendedServiceDescriptor.StartMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyWorkingDirectory()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.Equal(ExpectedWorkingDirectory, this.extendedServiceDescriptor.WorkingDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyServiceLogonRight()
|
||||
{
|
||||
Assert.True(this.extendedServiceDescriptor.AllowServiceAcountLogonRight);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyUsername()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.Equal(Domain + "\\" + Username, this.extendedServiceDescriptor.ServiceAccountUserName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyPassword()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.Equal(Password, this.extendedServiceDescriptor.ServiceAccountPassword);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Priority()
|
||||
{
|
||||
var sd = ServiceDescriptor.FromXml("<service><id>test</id><priority>normal</priority></service>");
|
||||
Assert.Equal(ProcessPriorityClass.Normal, sd.Priority);
|
||||
|
||||
sd = ServiceDescriptor.FromXml("<service><id>test</id><priority>idle</priority></service>");
|
||||
Assert.Equal(ProcessPriorityClass.Idle, sd.Priority);
|
||||
|
||||
sd = ServiceDescriptor.FromXml("<service><id>test</id></service>");
|
||||
Assert.Equal(ProcessPriorityClass.Normal, sd.Priority);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseStopTimeout()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<stoptimeout>60sec</stoptimeout>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal(TimeSpan.FromSeconds(60), serviceDescriptor.StopTimeout);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseStopTimeoutFromMinutes()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<stoptimeout>10min</stoptimeout>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal(TimeSpan.FromMinutes(10), serviceDescriptor.StopTimeout);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseLogname()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<logname>MyTestApp</logname>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal("MyTestApp", serviceDescriptor.LogName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseOutfileDisabled()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<outfiledisabled>true</outfiledisabled>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.True(serviceDescriptor.OutFileDisabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseErrfileDisabled()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<errfiledisabled>true</errfiledisabled>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.True(serviceDescriptor.ErrFileDisabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseOutfilePattern()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<outfilepattern>.out.test.log</outfilepattern>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal(".out.test.log", serviceDescriptor.OutFilePattern);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseErrfilePattern()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<errfilepattern>.err.test.log</errfilepattern>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal(".err.test.log", serviceDescriptor.ErrFilePattern);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogModeRollBySize()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<logpath>c:\\</logpath>"
|
||||
+ "<log mode=\"roll-by-size\">"
|
||||
+ "<sizeThreshold>112</sizeThreshold>"
|
||||
+ "<keepFiles>113</keepFiles>"
|
||||
+ "</log>"
|
||||
+ "</service>";
|
||||
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
var logHandler = serviceDescriptor.LogHandler as SizeBasedRollingLogAppender;
|
||||
Assert.NotNull(logHandler);
|
||||
Assert.Equal(112 * 1024, logHandler.SizeThreshold);
|
||||
Assert.Equal(113, logHandler.FilesToKeep);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogModeRollByTime()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<logpath>c:\\</logpath>"
|
||||
+ "<log mode=\"roll-by-time\">"
|
||||
+ "<period>7</period>"
|
||||
+ "<pattern>log pattern</pattern>"
|
||||
+ "</log>"
|
||||
+ "</service>";
|
||||
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
var logHandler = serviceDescriptor.LogHandler as TimeBasedRollingLogAppender;
|
||||
Assert.NotNull(logHandler);
|
||||
Assert.Equal(7, logHandler.Period);
|
||||
Assert.Equal("log pattern", logHandler.Pattern);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogModeRollBySizeTime()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<logpath>c:\\</logpath>"
|
||||
+ "<log mode=\"roll-by-size-time\">"
|
||||
+ "<sizeThreshold>10240</sizeThreshold>"
|
||||
+ "<pattern>yyyy-MM-dd</pattern>"
|
||||
+ "<autoRollAtTime>00:00:00</autoRollAtTime>"
|
||||
+ "</log>"
|
||||
+ "</service>";
|
||||
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
var logHandler = serviceDescriptor.LogHandler as RollingSizeTimeLogAppender;
|
||||
Assert.NotNull(logHandler);
|
||||
Assert.Equal(10240 * 1024, logHandler.SizeThreshold);
|
||||
Assert.Equal("yyyy-MM-dd", logHandler.FilePattern);
|
||||
Assert.Equal((TimeSpan?)new TimeSpan(0, 0, 0), logHandler.AutoRollAtTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyServiceLogonRightGraceful()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<serviceaccount>"
|
||||
+ "<domain>" + Domain + "</domain>"
|
||||
+ "<user>" + Username + "</user>"
|
||||
+ "<password>" + Password + "</password>"
|
||||
+ "<allowservicelogon>true1</allowservicelogon>"
|
||||
+ "</serviceaccount>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
Assert.False(serviceDescriptor.AllowServiceAcountLogonRight);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyServiceLogonRightOmitted()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<serviceaccount>"
|
||||
+ "<domain>" + Domain + "</domain>"
|
||||
+ "<user>" + Username + "</user>"
|
||||
+ "<password>" + Password + "</password>"
|
||||
+ "</serviceaccount>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
Assert.False(serviceDescriptor.AllowServiceAcountLogonRight);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyWaitHint_FullXML()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create()
|
||||
.WithTag("waithint", "20 min")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromMinutes(20), sd.WaitHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for https://github.com/kohsuke/winsw/issues/159
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void VerifyWaitHint_XMLWithoutVersion()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create(printXMLVersion: false)
|
||||
.WithTag("waithint", "21 min")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromMinutes(21), sd.WaitHint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyWaitHint_XMLWithoutComment()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create(xmlComment: null)
|
||||
.WithTag("waithint", "22 min")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromMinutes(22), sd.WaitHint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyWaitHint_XMLWithoutVersionAndComment()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create(xmlComment: null, printXMLVersion: false)
|
||||
.WithTag("waithint", "23 min")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromMinutes(23), sd.WaitHint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifySleepTime()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create().WithTag("sleeptime", "3 hrs").ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromHours(3), sd.SleepTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyResetFailureAfter()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create().WithTag("resetfailure", "75 sec").ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromSeconds(75), sd.ResetFailureAfter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyStopTimeout()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create().WithTag("stoptimeout", "35 secs").ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromSeconds(35), sd.StopTimeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://github.com/kohsuke/winsw/issues/178
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Arguments_LegacyParam()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create().WithTag("arguments", "arg").ToServiceDescriptor(true);
|
||||
Assert.Equal("arg", sd.Arguments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Arguments_NewParam_Single()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create()
|
||||
.WithTag("argument", "--arg1=2")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(" --arg1=2", sd.Arguments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Arguments_NewParam_MultipleArgs()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create()
|
||||
.WithTag("argument", "--arg1=2")
|
||||
.WithTag("argument", "--arg2=123")
|
||||
.WithTag("argument", "--arg3=null")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(" --arg1=2 --arg2=123 --arg3=null", sd.Arguments);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the new single-argument field has a higher priority.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Arguments_Bothparam_Priorities()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create()
|
||||
.WithTag("arguments", "--arg1=2 --arg2=3")
|
||||
.WithTag("argument", "--arg2=123")
|
||||
.WithTag("argument", "--arg3=null")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(" --arg2=123 --arg3=null", sd.Arguments);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void DelayedStart_RoundTrip(bool enabled)
|
||||
{
|
||||
var bldr = ConfigXmlBuilder.Create();
|
||||
if (enabled)
|
||||
{
|
||||
bldr = bldr.WithDelayedAutoStart();
|
||||
}
|
||||
|
||||
var sd = bldr.ToServiceDescriptor();
|
||||
Assert.Equal(enabled, sd.DelayedAutoStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceProcess;
|
||||
using WinSW.Tests.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WinSW.Tests
|
||||
{
|
||||
public class ServiceDescriptorTests
|
||||
{
|
||||
private const string ExpectedWorkingDirectory = @"Z:\Path\SubPath";
|
||||
private const string Username = "User";
|
||||
private const string Password = "Password";
|
||||
private const string Domain = "Domain";
|
||||
private const string AllowServiceAccountLogonRight = "true";
|
||||
|
||||
private ServiceDescriptor extendedServiceDescriptor;
|
||||
|
||||
public ServiceDescriptorTests()
|
||||
{
|
||||
string seedXml =
|
||||
$@"<service>
|
||||
<id>service.exe</id>
|
||||
<name>Service</name>
|
||||
<description>The service.</description>
|
||||
<executable>node.exe</executable>
|
||||
<arguments>My Arguments</arguments>
|
||||
<log mode=""roll""></log>
|
||||
<serviceaccount>
|
||||
<username>{Domain}\{Username}</username>
|
||||
<password>{Password}</password>
|
||||
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||
</serviceaccount>
|
||||
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||
<logpath>C:\logs</logpath>
|
||||
</service>";
|
||||
this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultStartMode()
|
||||
{
|
||||
Assert.Equal(ServiceStartMode.Automatic, this.extendedServiceDescriptor.StartMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncorrectStartMode()
|
||||
{
|
||||
string seedXml =
|
||||
$@"<service>
|
||||
<id>service.exe</id>
|
||||
<name>Service</name>
|
||||
<description>The service.</description>
|
||||
<executable>node.exe</executable>
|
||||
<arguments>My Arguments</arguments>
|
||||
<startmode>roll</startmode>
|
||||
<log mode=""roll""></log>
|
||||
<serviceaccount>
|
||||
<username>{Domain}\{Username}</username>
|
||||
<password>{Password}</password>
|
||||
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||
</serviceaccount>
|
||||
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||
<logpath>C:\logs</logpath>
|
||||
</service>";
|
||||
|
||||
this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
Assert.Throws<ArgumentException>(() => this.extendedServiceDescriptor.StartMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChangedStartMode()
|
||||
{
|
||||
string seedXml =
|
||||
$@"<service>
|
||||
<id>service.exe</id>
|
||||
<name>Service</name>
|
||||
<description>The service.</description>
|
||||
<executable>node.exe</executable>
|
||||
<arguments>My Arguments</arguments>
|
||||
<startmode>manual</startmode>
|
||||
<log mode=""roll""></log>
|
||||
<serviceaccount>
|
||||
<username>{Domain}\{Username}</username>
|
||||
<password>{Password}</password>
|
||||
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||
</serviceaccount>
|
||||
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||
<logpath>C:\logs</logpath>
|
||||
</service>";
|
||||
|
||||
this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
Assert.Equal(ServiceStartMode.Manual, this.extendedServiceDescriptor.StartMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyWorkingDirectory()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.Equal(ExpectedWorkingDirectory, this.extendedServiceDescriptor.WorkingDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyServiceLogonRight()
|
||||
{
|
||||
Assert.True(this.extendedServiceDescriptor.AllowServiceAcountLogonRight);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyUsername()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.Equal(Domain + "\\" + Username, this.extendedServiceDescriptor.ServiceAccountUserName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyPassword()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.Equal(Password, this.extendedServiceDescriptor.ServiceAccountPassword);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Priority()
|
||||
{
|
||||
var sd = ServiceDescriptor.FromXml("<service><id>test</id><priority>normal</priority></service>");
|
||||
Assert.Equal(ProcessPriorityClass.Normal, sd.Priority);
|
||||
|
||||
sd = ServiceDescriptor.FromXml("<service><id>test</id><priority>idle</priority></service>");
|
||||
Assert.Equal(ProcessPriorityClass.Idle, sd.Priority);
|
||||
|
||||
sd = ServiceDescriptor.FromXml("<service><id>test</id></service>");
|
||||
Assert.Equal(ProcessPriorityClass.Normal, sd.Priority);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseStopTimeout()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<stoptimeout>60sec</stoptimeout>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal(TimeSpan.FromSeconds(60), serviceDescriptor.StopTimeout);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseStopTimeoutFromMinutes()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<stoptimeout>10min</stoptimeout>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal(TimeSpan.FromMinutes(10), serviceDescriptor.StopTimeout);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseLogname()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<logname>MyTestApp</logname>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal("MyTestApp", serviceDescriptor.LogName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseOutfileDisabled()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<outfiledisabled>true</outfiledisabled>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.True(serviceDescriptor.OutFileDisabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseErrfileDisabled()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<errfiledisabled>true</errfiledisabled>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.True(serviceDescriptor.ErrFileDisabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseOutfilePattern()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<outfilepattern>.out.test.log</outfilepattern>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal(".out.test.log", serviceDescriptor.OutFilePattern);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseErrfilePattern()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<errfilepattern>.err.test.log</errfilepattern>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
|
||||
Assert.Equal(".err.test.log", serviceDescriptor.ErrFilePattern);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogModeRollBySize()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<logpath>c:\\</logpath>"
|
||||
+ "<log mode=\"roll-by-size\">"
|
||||
+ "<sizeThreshold>112</sizeThreshold>"
|
||||
+ "<keepFiles>113</keepFiles>"
|
||||
+ "</log>"
|
||||
+ "</service>";
|
||||
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
var logHandler = serviceDescriptor.LogHandler as SizeBasedRollingLogAppender;
|
||||
Assert.NotNull(logHandler);
|
||||
Assert.Equal(112 * 1024, logHandler.SizeThreshold);
|
||||
Assert.Equal(113, logHandler.FilesToKeep);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogModeRollByTime()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<logpath>c:\\</logpath>"
|
||||
+ "<log mode=\"roll-by-time\">"
|
||||
+ "<period>7</period>"
|
||||
+ "<pattern>log pattern</pattern>"
|
||||
+ "</log>"
|
||||
+ "</service>";
|
||||
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
var logHandler = serviceDescriptor.LogHandler as TimeBasedRollingLogAppender;
|
||||
Assert.NotNull(logHandler);
|
||||
Assert.Equal(7, logHandler.Period);
|
||||
Assert.Equal("log pattern", logHandler.Pattern);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogModeRollBySizeTime()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<logpath>c:\\</logpath>"
|
||||
+ "<log mode=\"roll-by-size-time\">"
|
||||
+ "<sizeThreshold>10240</sizeThreshold>"
|
||||
+ "<pattern>yyyy-MM-dd</pattern>"
|
||||
+ "<autoRollAtTime>00:00:00</autoRollAtTime>"
|
||||
+ "</log>"
|
||||
+ "</service>";
|
||||
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
var logHandler = serviceDescriptor.LogHandler as RollingSizeTimeLogAppender;
|
||||
Assert.NotNull(logHandler);
|
||||
Assert.Equal(10240 * 1024, logHandler.SizeThreshold);
|
||||
Assert.Equal("yyyy-MM-dd", logHandler.FilePattern);
|
||||
Assert.Equal((TimeSpan?)new TimeSpan(0, 0, 0), logHandler.AutoRollAtTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyServiceLogonRightGraceful()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<serviceaccount>"
|
||||
+ "<domain>" + Domain + "</domain>"
|
||||
+ "<user>" + Username + "</user>"
|
||||
+ "<password>" + Password + "</password>"
|
||||
+ "<allowservicelogon>true1</allowservicelogon>"
|
||||
+ "</serviceaccount>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
Assert.False(serviceDescriptor.AllowServiceAcountLogonRight);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyServiceLogonRightOmitted()
|
||||
{
|
||||
const string seedXml = "<service>"
|
||||
+ "<serviceaccount>"
|
||||
+ "<domain>" + Domain + "</domain>"
|
||||
+ "<user>" + Username + "</user>"
|
||||
+ "<password>" + Password + "</password>"
|
||||
+ "</serviceaccount>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = ServiceDescriptor.FromXml(seedXml);
|
||||
Assert.False(serviceDescriptor.AllowServiceAcountLogonRight);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyWaitHint_FullXML()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create()
|
||||
.WithTag("waithint", "20 min")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromMinutes(20), sd.WaitHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for https://github.com/kohsuke/winsw/issues/159
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void VerifyWaitHint_XMLWithoutVersion()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create(printXMLVersion: false)
|
||||
.WithTag("waithint", "21 min")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromMinutes(21), sd.WaitHint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyWaitHint_XMLWithoutComment()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create(xmlComment: null)
|
||||
.WithTag("waithint", "22 min")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromMinutes(22), sd.WaitHint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyWaitHint_XMLWithoutVersionAndComment()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create(xmlComment: null, printXMLVersion: false)
|
||||
.WithTag("waithint", "23 min")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromMinutes(23), sd.WaitHint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifySleepTime()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create().WithTag("sleeptime", "3 hrs").ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromHours(3), sd.SleepTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyResetFailureAfter()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create().WithTag("resetfailure", "75 sec").ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromSeconds(75), sd.ResetFailureAfter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyStopTimeout()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create().WithTag("stoptimeout", "35 secs").ToServiceDescriptor(true);
|
||||
Assert.Equal(TimeSpan.FromSeconds(35), sd.StopTimeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://github.com/kohsuke/winsw/issues/178
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Arguments_LegacyParam()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create().WithTag("arguments", "arg").ToServiceDescriptor(true);
|
||||
Assert.Equal("arg", sd.Arguments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Arguments_NewParam_Single()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create()
|
||||
.WithTag("argument", "--arg1=2")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(" --arg1=2", sd.Arguments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Arguments_NewParam_MultipleArgs()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create()
|
||||
.WithTag("argument", "--arg1=2")
|
||||
.WithTag("argument", "--arg2=123")
|
||||
.WithTag("argument", "--arg3=null")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(" --arg1=2 --arg2=123 --arg3=null", sd.Arguments);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the new single-argument field has a higher priority.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Arguments_Bothparam_Priorities()
|
||||
{
|
||||
var sd = ConfigXmlBuilder.Create()
|
||||
.WithTag("arguments", "--arg1=2 --arg2=3")
|
||||
.WithTag("argument", "--arg2=123")
|
||||
.WithTag("argument", "--arg3=null")
|
||||
.ToServiceDescriptor(true);
|
||||
Assert.Equal(" --arg2=123 --arg3=null", sd.Arguments);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void DelayedStart_RoundTrip(bool enabled)
|
||||
{
|
||||
var bldr = ConfigXmlBuilder.Create();
|
||||
if (enabled)
|
||||
{
|
||||
bldr = bldr.WithDelayedAutoStart();
|
||||
}
|
||||
|
||||
var sd = bldr.ToServiceDescriptor();
|
||||
Assert.Equal(enabled, sd.DelayedAutoStart);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp3.1</TargetFrameworks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
||||
<RootNamespace>winswTests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -26,10 +24,9 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\ServiceWrapper\winsw.csproj" />
|
||||
<ProjectReference Include="..\..\Core\WinSWCore\WinSWCore.csproj" />
|
||||
<ProjectReference Include="..\..\Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj" />
|
||||
<ProjectReference Include="..\..\Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj" />
|
||||
<ProjectReference Include="..\WinSW\WinSW.csproj" />
|
||||
<ProjectReference Include="..\WinSW.Core\WinSW.Core.csproj" />
|
||||
<ProjectReference Include="..\WinSW.Plugins\WinSW.Plugins.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30128.74
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinSW", "WinSW\WinSW.csproj", "{87BD4253-6957-4D83-B75D-5C4C2F114694}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinSW.Core", "WinSW.Core\WinSW.Core.csproj", "{560E6F6A-18DD-4245-AD1A-D02A9AB9CDD7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinSW.Plugins", "WinSW.Plugins\WinSW.Plugins.csproj", "{B50AD8AA-54BD-4FD9-95A9-8AADC84DD46E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinSW.Tests", "WinSW.Tests\WinSW.Tests.csproj", "{691DE22D-4565-4E3C-9CC7-918A0098219E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4975DCF4-C32C-43ED-A731-8FCC1F7E6746}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{87BD4253-6957-4D83-B75D-5C4C2F114694}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{87BD4253-6957-4D83-B75D-5C4C2F114694}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{87BD4253-6957-4D83-B75D-5C4C2F114694}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{87BD4253-6957-4D83-B75D-5C4C2F114694}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{560E6F6A-18DD-4245-AD1A-D02A9AB9CDD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{560E6F6A-18DD-4245-AD1A-D02A9AB9CDD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{560E6F6A-18DD-4245-AD1A-D02A9AB9CDD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{560E6F6A-18DD-4245-AD1A-D02A9AB9CDD7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B50AD8AA-54BD-4FD9-95A9-8AADC84DD46E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B50AD8AA-54BD-4FD9-95A9-8AADC84DD46E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B50AD8AA-54BD-4FD9-95A9-8AADC84DD46E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B50AD8AA-54BD-4FD9-95A9-8AADC84DD46E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{691DE22D-4565-4E3C-9CC7-918A0098219E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{691DE22D-4565-4E3C-9CC7-918A0098219E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{691DE22D-4565-4E3C-9CC7-918A0098219E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{691DE22D-4565-4E3C-9CC7-918A0098219E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {A508CEB3-957E-4B4D-9365-60E5A35EA009}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,3 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WinSW.Tests")]
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
|
@ -12,8 +12,6 @@
|
|||
<Company>CloudBees, Inc.</Company>
|
||||
<Product>Windows Service Wrapper</Product>
|
||||
<Copyright>Copyright 2008-2016 Oleg Nenashev, CloudBees, Inc. and other contributors</Copyright>
|
||||
<RootNamespace>winsw</RootNamespace>
|
||||
<AssemblyName>WindowsService</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
|
||||
|
@ -31,9 +29,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WinSWCore\WinSWCore.csproj" />
|
||||
<ProjectReference Include="..\..\Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj" />
|
||||
<ProjectReference Include="..\..\Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj" />
|
||||
<ProjectReference Include="..\WinSW.Core\WinSW.Core.csproj" />
|
||||
<ProjectReference Include="..\WinSW.Plugins\WinSW.Plugins.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PublishCoreZip" AfterTargets="Publish" Condition="'$(TargetFramework)' == 'netcoreapp3.1' and '$(RuntimeIdentifier)' == ''">
|
||||
|
@ -67,9 +64,8 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<InputAssemblies>"$(OutDir)$(TargetFileName)"</InputAssemblies>
|
||||
<InputAssemblies>$(InputAssemblies) "$(OutDir)WinSWCore.dll"</InputAssemblies>
|
||||
<InputAssemblies>$(InputAssemblies) "$(OutDir)SharedDirectoryMapper.dll"</InputAssemblies>
|
||||
<InputAssemblies>$(InputAssemblies) "$(OutDir)RunawayProcessKiller.dll"</InputAssemblies>
|
||||
<InputAssemblies>$(InputAssemblies) "$(OutDir)WinSW.Core.dll"</InputAssemblies>
|
||||
<InputAssemblies>$(InputAssemblies) "$(OutDir)WinSW.Plugins.dll"</InputAssemblies>
|
||||
<InputAssemblies>$(InputAssemblies) "$(OutDir)log4net.dll"</InputAssemblies>
|
||||
<OutputAssembly>"$(ArtifactsDir)WinSW.$(IdentifierSuffix).exe"</OutputAssembly>
|
||||
</PropertyGroup>
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
|
@ -1,91 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30128.74
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "winsw", "Core\ServiceWrapper\winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "winswTests", "Test\winswTests\winswTests.csproj", "{93843402-842B-44B4-B303-AEE829BE0B43}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedDirectoryMapper", "Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj", "{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{077C2CEC-B687-4B53-86E9-C1A1BF5554E5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{BC4AD891-E87E-4F30-867C-FD8084A29E5D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5297623A-1A95-4F89-9AAE-DA634081EC86}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinSWCore", "Core\WinSWCore\WinSWCore.csproj", "{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RunawayProcessKiller", "Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj", "{57284B7A-82A4-407A-B706-EBEA6BF8EA13}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AA414F46-B863-473A-A0E0-C2971B3396AE}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
..\samples\sample-complete.xml = ..\samples\sample-complete.xml
|
||||
..\samples\sample-minimal.xml = ..\samples\sample-minimal.xml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Win32.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
|
||||
{93843402-842B-44B4-B303-AEE829BE0B43} = {077C2CEC-B687-4B53-86E9-C1A1BF5554E5}
|
||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
|
||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
|
||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F9F8AFEA-196D-4041-8441-FABC3B730F9E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Loading…
Reference in New Issue