mirror of https://github.com/winsw/winsw
Fix file permission and line ending issues
parent
139c98403b
commit
7554d0ecbd
|
@ -1,280 +1,280 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
#if !VNEXT
|
#if !VNEXT
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
#endif
|
#endif
|
||||||
using System.Text;
|
using System.Text;
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
#endif
|
#endif
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using log4net;
|
using log4net;
|
||||||
using WinSW.Util;
|
using WinSW.Util;
|
||||||
|
|
||||||
namespace WinSW
|
namespace WinSW
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specify the download activities prior to the launch.
|
/// Specify the download activities prior to the launch.
|
||||||
/// This enables self-updating services.
|
/// This enables self-updating services.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Download
|
public class Download
|
||||||
{
|
{
|
||||||
public enum AuthType
|
public enum AuthType
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Sspi,
|
Sspi,
|
||||||
Basic
|
Basic
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly ILog Logger = LogManager.GetLogger(typeof(Download));
|
private static readonly ILog Logger = LogManager.GetLogger(typeof(Download));
|
||||||
|
|
||||||
public readonly string From;
|
public readonly string From;
|
||||||
public readonly string To;
|
public readonly string To;
|
||||||
public readonly AuthType Auth;
|
public readonly AuthType Auth;
|
||||||
public readonly string? Username;
|
public readonly string? Username;
|
||||||
public readonly string? Password;
|
public readonly string? Password;
|
||||||
public readonly bool UnsecureAuth;
|
public readonly bool UnsecureAuth;
|
||||||
public readonly bool FailOnError;
|
public readonly bool FailOnError;
|
||||||
public readonly string? Proxy;
|
public readonly string? Proxy;
|
||||||
|
|
||||||
public string ShortId => $"(download from {this.From})";
|
public string ShortId => $"(download from {this.From})";
|
||||||
|
|
||||||
static Download()
|
static Download()
|
||||||
{
|
{
|
||||||
#if NET461
|
#if NET461
|
||||||
// If your app runs on .NET Framework 4.7 or later versions, but targets an earlier version
|
// If your app runs on .NET Framework 4.7 or later versions, but targets an earlier version
|
||||||
AppContext.SetSwitch("Switch.System.Net.DontEnableSystemDefaultTlsVersions", false);
|
AppContext.SetSwitch("Switch.System.Net.DontEnableSystemDefaultTlsVersions", false);
|
||||||
#elif !VNEXT
|
#elif !VNEXT
|
||||||
// If your app runs on .NET Framework 4.6, but targets an earlier version
|
// If your app runs on .NET Framework 4.6, but targets an earlier version
|
||||||
Type.GetType("System.AppContext")?.InvokeMember("SetSwitch", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { "Switch.System.Net.DontEnableSchUseStrongCrypto", false });
|
Type.GetType("System.AppContext")?.InvokeMember("SetSwitch", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { "Switch.System.Net.DontEnableSchUseStrongCrypto", false });
|
||||||
|
|
||||||
const SecurityProtocolType Tls12 = (SecurityProtocolType)0x00000C00;
|
const SecurityProtocolType Tls12 = (SecurityProtocolType)0x00000C00;
|
||||||
const SecurityProtocolType Tls11 = (SecurityProtocolType)0x00000300;
|
const SecurityProtocolType Tls11 = (SecurityProtocolType)0x00000300;
|
||||||
|
|
||||||
// Windows 7 and Windows Server 2008 R2
|
// Windows 7 and Windows Server 2008 R2
|
||||||
if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 1)
|
if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 1)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ServicePointManager.SecurityProtocol |= Tls11 | Tls12;
|
ServicePointManager.SecurityProtocol |= Tls11 | Tls12;
|
||||||
Logger.Info("TLS 1.1/1.2 enabled");
|
Logger.Info("TLS 1.1/1.2 enabled");
|
||||||
}
|
}
|
||||||
catch (NotSupportedException)
|
catch (NotSupportedException)
|
||||||
{
|
{
|
||||||
Logger.Info("TLS 1.1/1.2 disabled");
|
Logger.Info("TLS 1.1/1.2 disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal
|
// internal
|
||||||
public Download(
|
public Download(
|
||||||
string from,
|
string from,
|
||||||
string to,
|
string to,
|
||||||
bool failOnError = false,
|
bool failOnError = false,
|
||||||
AuthType auth = AuthType.None,
|
AuthType auth = AuthType.None,
|
||||||
string? username = null,
|
string? username = null,
|
||||||
string? password = null,
|
string? password = null,
|
||||||
bool unsecureAuth = false,
|
bool unsecureAuth = false,
|
||||||
string? proxy = null)
|
string? proxy = null)
|
||||||
{
|
{
|
||||||
this.From = from;
|
this.From = from;
|
||||||
this.To = to;
|
this.To = to;
|
||||||
this.FailOnError = failOnError;
|
this.FailOnError = failOnError;
|
||||||
this.Proxy = proxy;
|
this.Proxy = proxy;
|
||||||
this.Auth = auth;
|
this.Auth = auth;
|
||||||
this.Username = username;
|
this.Username = username;
|
||||||
this.Password = password;
|
this.Password = password;
|
||||||
this.UnsecureAuth = unsecureAuth;
|
this.UnsecureAuth = unsecureAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs the download setting sfrom the XML entry
|
/// Constructs the download setting sfrom the XML entry
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="n">XML element</param>
|
/// <param name="n">XML element</param>
|
||||||
/// <exception cref="InvalidDataException">The required attribute is missing or the configuration is invalid.</exception>
|
/// <exception cref="InvalidDataException">The required attribute is missing or the configuration is invalid.</exception>
|
||||||
internal Download(XmlElement n)
|
internal Download(XmlElement n)
|
||||||
{
|
{
|
||||||
this.From = XmlHelper.SingleAttribute<string>(n, "from");
|
this.From = XmlHelper.SingleAttribute<string>(n, "from");
|
||||||
this.To = XmlHelper.SingleAttribute<string>(n, "to");
|
this.To = XmlHelper.SingleAttribute<string>(n, "to");
|
||||||
|
|
||||||
// All arguments below are optional
|
// All arguments below are optional
|
||||||
this.FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false);
|
this.FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false);
|
||||||
this.Proxy = XmlHelper.SingleAttribute<string>(n, "proxy", null);
|
this.Proxy = XmlHelper.SingleAttribute<string>(n, "proxy", null);
|
||||||
|
|
||||||
this.Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.None);
|
this.Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.None);
|
||||||
this.Username = XmlHelper.SingleAttribute<string>(n, "user", null);
|
this.Username = XmlHelper.SingleAttribute<string>(n, "user", null);
|
||||||
this.Password = XmlHelper.SingleAttribute<string>(n, "password", null);
|
this.Password = XmlHelper.SingleAttribute<string>(n, "password", null);
|
||||||
this.UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false);
|
this.UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false);
|
||||||
|
|
||||||
if (this.Auth == AuthType.Basic)
|
if (this.Auth == AuthType.Basic)
|
||||||
{
|
{
|
||||||
// Allow it only for HTTPS or for UnsecureAuth
|
// Allow it only for HTTPS or for UnsecureAuth
|
||||||
if (!this.From.StartsWith("https:") && !this.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 +
|
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");
|
"If you really want this you must enable 'unsecureAuth' in the configuration");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also fail if there is no user/password
|
// Also fail if there is no user/password
|
||||||
if (this.Username is null)
|
if (this.Username is null)
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + this.ShortId);
|
throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + this.ShortId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.Password is null)
|
if (this.Password is null)
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("Basic Auth is enabled, but password is not specified " + this.ShortId);
|
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
|
// Source: http://stackoverflow.com/questions/2764577/forcing-basic-authentication-in-webrequest
|
||||||
private void SetBasicAuthHeader(WebRequest request, string username, string password)
|
private void SetBasicAuthHeader(WebRequest request, string username, string password)
|
||||||
{
|
{
|
||||||
string authInfo = username + ":" + password;
|
string authInfo = username + ":" + password;
|
||||||
authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(authInfo));
|
authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(authInfo));
|
||||||
request.Headers["Authorization"] = "Basic " + authInfo;
|
request.Headers["Authorization"] = "Basic " + authInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Downloads the requested file and puts it to the specified target.
|
/// Downloads the requested file and puts it to the specified target.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="WebException">
|
/// <exception cref="WebException">
|
||||||
/// Download failure. FailOnError flag should be processed outside.
|
/// Download failure. FailOnError flag should be processed outside.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
public async Task PerformAsync()
|
public async Task PerformAsync()
|
||||||
#else
|
#else
|
||||||
public void Perform()
|
public void Perform()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
WebRequest request = WebRequest.Create(this.From);
|
WebRequest request = WebRequest.Create(this.From);
|
||||||
if (!string.IsNullOrEmpty(this.Proxy))
|
if (!string.IsNullOrEmpty(this.Proxy))
|
||||||
{
|
{
|
||||||
CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!);
|
CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!);
|
||||||
if (proxyInformation.Credentials != null)
|
if (proxyInformation.Credentials != null)
|
||||||
{
|
{
|
||||||
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
|
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
request.Proxy = new WebProxy(proxyInformation.ServerAddress);
|
request.Proxy = new WebProxy(proxyInformation.ServerAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (this.Auth)
|
switch (this.Auth)
|
||||||
{
|
{
|
||||||
case AuthType.None:
|
case AuthType.None:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AuthType.Sspi:
|
case AuthType.Sspi:
|
||||||
request.UseDefaultCredentials = true;
|
request.UseDefaultCredentials = true;
|
||||||
request.PreAuthenticate = true;
|
request.PreAuthenticate = true;
|
||||||
request.Credentials = CredentialCache.DefaultCredentials;
|
request.Credentials = CredentialCache.DefaultCredentials;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AuthType.Basic:
|
case AuthType.Basic:
|
||||||
this.SetBasicAuthHeader(request, this.Username!, this.Password!);
|
this.SetBasicAuthHeader(request, this.Username!, this.Password!);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new WebException("Code defect. Unsupported authentication type: " + this.Auth);
|
throw new WebException("Code defect. Unsupported authentication type: " + this.Auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsIfModifiedSince = false;
|
bool supportsIfModifiedSince = false;
|
||||||
if (request is HttpWebRequest httpRequest && File.Exists(this.To))
|
if (request is HttpWebRequest httpRequest && File.Exists(this.To))
|
||||||
{
|
{
|
||||||
supportsIfModifiedSince = true;
|
supportsIfModifiedSince = true;
|
||||||
httpRequest.IfModifiedSince = File.GetLastWriteTime(this.To);
|
httpRequest.IfModifiedSince = File.GetLastWriteTime(this.To);
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime lastModified = default;
|
DateTime lastModified = default;
|
||||||
string tmpFilePath = this.To + ".tmp";
|
string tmpFilePath = this.To + ".tmp";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
using (WebResponse response = await request.GetResponseAsync())
|
using (WebResponse response = await request.GetResponseAsync())
|
||||||
#else
|
#else
|
||||||
using (WebResponse response = request.GetResponse())
|
using (WebResponse response = request.GetResponse())
|
||||||
#endif
|
#endif
|
||||||
using (Stream responseStream = response.GetResponseStream())
|
using (Stream responseStream = response.GetResponseStream())
|
||||||
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
||||||
{
|
{
|
||||||
if (supportsIfModifiedSince)
|
if (supportsIfModifiedSince)
|
||||||
{
|
{
|
||||||
lastModified = ((HttpWebResponse)response).LastModified;
|
lastModified = ((HttpWebResponse)response).LastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
await responseStream.CopyToAsync(tmpStream);
|
await responseStream.CopyToAsync(tmpStream);
|
||||||
#elif NET20
|
#elif NET20
|
||||||
CopyStream(responseStream, tmpStream);
|
CopyStream(responseStream, tmpStream);
|
||||||
#else
|
#else
|
||||||
responseStream.CopyTo(tmpStream);
|
responseStream.CopyTo(tmpStream);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To);
|
FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To);
|
||||||
|
|
||||||
if (supportsIfModifiedSince)
|
if (supportsIfModifiedSince)
|
||||||
{
|
{
|
||||||
File.SetLastWriteTime(this.To, lastModified);
|
File.SetLastWriteTime(this.To, lastModified);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (WebException e)
|
catch (WebException e)
|
||||||
{
|
{
|
||||||
if (supportsIfModifiedSince && ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified)
|
if (supportsIfModifiedSince && ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified)
|
||||||
{
|
{
|
||||||
Logger.Info($"Skipped downloading unmodified resource '{this.From}'");
|
Logger.Info($"Skipped downloading unmodified resource '{this.From}'");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NET20
|
#if NET20
|
||||||
private static void CopyStream(Stream source, Stream destination)
|
private static void CopyStream(Stream source, Stream destination)
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[8192];
|
byte[] buffer = new byte[8192];
|
||||||
int read;
|
int read;
|
||||||
while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
|
while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
|
||||||
{
|
{
|
||||||
destination.Write(buffer, 0, read);
|
destination.Write(buffer, 0, read);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CustomProxyInformation
|
public class CustomProxyInformation
|
||||||
{
|
{
|
||||||
public string ServerAddress { get; set; }
|
public string ServerAddress { get; set; }
|
||||||
|
|
||||||
public NetworkCredential? Credentials { get; set; }
|
public NetworkCredential? Credentials { get; set; }
|
||||||
|
|
||||||
public CustomProxyInformation(string proxy)
|
public CustomProxyInformation(string proxy)
|
||||||
{
|
{
|
||||||
if (proxy.Contains("@"))
|
if (proxy.Contains("@"))
|
||||||
{
|
{
|
||||||
// Extract proxy credentials
|
// Extract proxy credentials
|
||||||
int credsFrom = proxy.IndexOf("://") + 3;
|
int credsFrom = proxy.IndexOf("://") + 3;
|
||||||
int credsTo = proxy.LastIndexOf("@");
|
int credsTo = proxy.LastIndexOf("@");
|
||||||
string completeCredsStr = proxy.Substring(credsFrom, credsTo - credsFrom);
|
string completeCredsStr = proxy.Substring(credsFrom, credsTo - credsFrom);
|
||||||
int credsSeparator = completeCredsStr.IndexOf(":");
|
int credsSeparator = completeCredsStr.IndexOf(":");
|
||||||
|
|
||||||
string username = completeCredsStr.Substring(0, credsSeparator);
|
string username = completeCredsStr.Substring(0, credsSeparator);
|
||||||
string password = completeCredsStr.Substring(credsSeparator + 1);
|
string password = completeCredsStr.Substring(credsSeparator + 1);
|
||||||
this.Credentials = new NetworkCredential(username, password);
|
this.Credentials = new NetworkCredential(username, password);
|
||||||
this.ServerAddress = proxy.Replace(completeCredsStr + "@", string.Empty);
|
this.ServerAddress = proxy.Replace(completeCredsStr + "@", string.Empty);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.ServerAddress = proxy;
|
this.ServerAddress = proxy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,205 +1,205 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
|
|
||||||
namespace DynamicProxy
|
namespace DynamicProxy
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface that a user defined proxy handler needs to implement. This interface
|
/// Interface that a user defined proxy handler needs to implement. This interface
|
||||||
/// defines one method that gets invoked by the generated proxy.
|
/// defines one method that gets invoked by the generated proxy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IProxyInvocationHandler
|
public interface IProxyInvocationHandler
|
||||||
{
|
{
|
||||||
/// <param name="proxy">The instance of the proxy</param>
|
/// <param name="proxy">The instance of the proxy</param>
|
||||||
/// <param name="method">The method info that can be used to invoke the actual method on the object implementation</param>
|
/// <param name="method">The method info that can be used to invoke the actual method on the object implementation</param>
|
||||||
/// <param name="parameters">Parameters to pass to the method</param>
|
/// <param name="parameters">Parameters to pass to the method</param>
|
||||||
/// <returns>Object</returns>
|
/// <returns>Object</returns>
|
||||||
object? Invoke(object proxy, MethodInfo method, object[] parameters);
|
object? Invoke(object proxy, MethodInfo method, object[] parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ProxyFactory
|
public static class ProxyFactory
|
||||||
{
|
{
|
||||||
private const string ProxySuffix = "Proxy";
|
private const string ProxySuffix = "Proxy";
|
||||||
private const string AssemblyName = "ProxyAssembly";
|
private const string AssemblyName = "ProxyAssembly";
|
||||||
private const string ModuleName = "ProxyModule";
|
private const string ModuleName = "ProxyModule";
|
||||||
private const string HandlerName = "handler";
|
private const string HandlerName = "handler";
|
||||||
|
|
||||||
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
|
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
|
||||||
|
|
||||||
private static readonly AssemblyBuilder AssemblyBuilder =
|
private static readonly AssemblyBuilder AssemblyBuilder =
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
AssemblyBuilder.DefineDynamicAssembly(
|
AssemblyBuilder.DefineDynamicAssembly(
|
||||||
#else
|
#else
|
||||||
AppDomain.CurrentDomain.DefineDynamicAssembly(
|
AppDomain.CurrentDomain.DefineDynamicAssembly(
|
||||||
#endif
|
#endif
|
||||||
new AssemblyName(AssemblyName), AssemblyBuilderAccess.Run);
|
new AssemblyName(AssemblyName), AssemblyBuilderAccess.Run);
|
||||||
|
|
||||||
private static readonly ModuleBuilder ModuleBuilder = AssemblyBuilder.DefineDynamicModule(ModuleName);
|
private static readonly ModuleBuilder ModuleBuilder = AssemblyBuilder.DefineDynamicModule(ModuleName);
|
||||||
|
|
||||||
public static object Create(IProxyInvocationHandler handler, Type objType, bool isObjInterface = false)
|
public static object Create(IProxyInvocationHandler handler, Type objType, bool isObjInterface = false)
|
||||||
{
|
{
|
||||||
string typeName = objType.FullName + ProxySuffix;
|
string typeName = objType.FullName + ProxySuffix;
|
||||||
Type? type = null;
|
Type? type = null;
|
||||||
lock (TypeCache)
|
lock (TypeCache)
|
||||||
{
|
{
|
||||||
if (!TypeCache.TryGetValue(typeName, out type))
|
if (!TypeCache.TryGetValue(typeName, out type))
|
||||||
{
|
{
|
||||||
type = CreateType(typeName, isObjInterface ? new Type[] { objType } : objType.GetInterfaces());
|
type = CreateType(typeName, isObjInterface ? new Type[] { objType } : objType.GetInterfaces());
|
||||||
TypeCache.Add(typeName, type);
|
TypeCache.Add(typeName, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Activator.CreateInstance(type, new object[] { handler })!;
|
return Activator.CreateInstance(type, new object[] { handler })!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type CreateType(string dynamicTypeName, Type[] interfaces)
|
private static Type CreateType(string dynamicTypeName, Type[] interfaces)
|
||||||
{
|
{
|
||||||
Type objType = typeof(object);
|
Type objType = typeof(object);
|
||||||
Type handlerType = typeof(IProxyInvocationHandler);
|
Type handlerType = typeof(IProxyInvocationHandler);
|
||||||
|
|
||||||
TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
|
TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
|
||||||
|
|
||||||
// Gather up the proxy information and create a new type builder. One that
|
// Gather up the proxy information and create a new type builder. One that
|
||||||
// inherits from Object and implements the interface passed in
|
// inherits from Object and implements the interface passed in
|
||||||
TypeBuilder typeBuilder = ModuleBuilder.DefineType(
|
TypeBuilder typeBuilder = ModuleBuilder.DefineType(
|
||||||
dynamicTypeName, typeAttributes, objType, interfaces);
|
dynamicTypeName, typeAttributes, objType, interfaces);
|
||||||
|
|
||||||
// Define a member variable to hold the delegate
|
// Define a member variable to hold the delegate
|
||||||
FieldBuilder handlerField = typeBuilder.DefineField(
|
FieldBuilder handlerField = typeBuilder.DefineField(
|
||||||
HandlerName, handlerType, FieldAttributes.Private | FieldAttributes.InitOnly);
|
HandlerName, handlerType, FieldAttributes.Private | FieldAttributes.InitOnly);
|
||||||
|
|
||||||
// build a constructor that takes the delegate object as the only argument
|
// build a constructor that takes the delegate object as the only argument
|
||||||
ConstructorInfo baseConstructor = objType.GetConstructor(Type.EmptyTypes)!;
|
ConstructorInfo baseConstructor = objType.GetConstructor(Type.EmptyTypes)!;
|
||||||
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
|
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
|
||||||
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
|
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
|
||||||
|
|
||||||
ILGenerator constructorIL = delegateConstructor.GetILGenerator();
|
ILGenerator constructorIL = delegateConstructor.GetILGenerator();
|
||||||
|
|
||||||
// Load "this"
|
// Load "this"
|
||||||
constructorIL.Emit(OpCodes.Ldarg_0);
|
constructorIL.Emit(OpCodes.Ldarg_0);
|
||||||
|
|
||||||
// Load first constructor parameter
|
// Load first constructor parameter
|
||||||
constructorIL.Emit(OpCodes.Ldarg_1);
|
constructorIL.Emit(OpCodes.Ldarg_1);
|
||||||
|
|
||||||
// Set the first parameter into the handler field
|
// Set the first parameter into the handler field
|
||||||
constructorIL.Emit(OpCodes.Stfld, handlerField);
|
constructorIL.Emit(OpCodes.Stfld, handlerField);
|
||||||
|
|
||||||
// Load "this"
|
// Load "this"
|
||||||
constructorIL.Emit(OpCodes.Ldarg_0);
|
constructorIL.Emit(OpCodes.Ldarg_0);
|
||||||
|
|
||||||
// Call the super constructor
|
// Call the super constructor
|
||||||
constructorIL.Emit(OpCodes.Call, baseConstructor);
|
constructorIL.Emit(OpCodes.Call, baseConstructor);
|
||||||
|
|
||||||
// Constructor return
|
// Constructor return
|
||||||
constructorIL.Emit(OpCodes.Ret);
|
constructorIL.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
// for every method that the interfaces define, build a corresponding
|
// for every method that the interfaces define, build a corresponding
|
||||||
// method in the dynamic type that calls the handlers invoke method.
|
// method in the dynamic type that calls the handlers invoke method.
|
||||||
foreach (Type interfaceType in interfaces)
|
foreach (Type interfaceType in interfaces)
|
||||||
{
|
{
|
||||||
GenerateMethod(interfaceType, handlerField, typeBuilder);
|
GenerateMethod(interfaceType, handlerField, typeBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeBuilder.CreateType()!;
|
return typeBuilder.CreateType()!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="IProxyInvocationHandler.Invoke(object, MethodInfo, object[])"/>.
|
/// <see cref="IProxyInvocationHandler.Invoke(object, MethodInfo, object[])"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly MethodInfo InvokeMethod = typeof(IProxyInvocationHandler).GetMethod(nameof(IProxyInvocationHandler.Invoke))!;
|
private static readonly MethodInfo InvokeMethod = typeof(IProxyInvocationHandler).GetMethod(nameof(IProxyInvocationHandler.Invoke))!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="MethodBase.GetMethodFromHandle(RuntimeMethodHandle)"/>.
|
/// <see cref="MethodBase.GetMethodFromHandle(RuntimeMethodHandle)"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly MethodInfo GetMethodFromHandleMethod = typeof(MethodBase).GetMethod(nameof(MethodBase.GetMethodFromHandle), new[] { typeof(RuntimeMethodHandle) })!;
|
private static readonly MethodInfo GetMethodFromHandleMethod = typeof(MethodBase).GetMethod(nameof(MethodBase.GetMethodFromHandle), new[] { typeof(RuntimeMethodHandle) })!;
|
||||||
|
|
||||||
private static void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
|
private static void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
|
||||||
{
|
{
|
||||||
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
|
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
|
||||||
|
|
||||||
for (int i = 0; i < interfaceMethods.Length; i++)
|
for (int i = 0; i < interfaceMethods.Length; i++)
|
||||||
{
|
{
|
||||||
MethodInfo methodInfo = interfaceMethods[i];
|
MethodInfo methodInfo = interfaceMethods[i];
|
||||||
|
|
||||||
// Get the method parameters since we need to create an array
|
// Get the method parameters since we need to create an array
|
||||||
// of parameter types
|
// of parameter types
|
||||||
ParameterInfo[] methodParams = methodInfo.GetParameters();
|
ParameterInfo[] methodParams = methodInfo.GetParameters();
|
||||||
int numOfParams = methodParams.Length;
|
int numOfParams = methodParams.Length;
|
||||||
Type[] methodParameters = new Type[numOfParams];
|
Type[] methodParameters = new Type[numOfParams];
|
||||||
|
|
||||||
// convert the ParameterInfo objects into Type
|
// 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;
|
methodParameters[j] = methodParams[j].ParameterType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new builder for the method in the interface
|
// create a new builder for the method in the interface
|
||||||
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
|
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
|
||||||
methodInfo.Name,
|
methodInfo.Name,
|
||||||
/*MethodAttributes.Public | MethodAttributes.Virtual | */ methodInfo.Attributes & ~MethodAttributes.Abstract,
|
/*MethodAttributes.Public | MethodAttributes.Virtual | */ methodInfo.Attributes & ~MethodAttributes.Abstract,
|
||||||
CallingConventions.Standard,
|
CallingConventions.Standard,
|
||||||
methodInfo.ReturnType,
|
methodInfo.ReturnType,
|
||||||
methodParameters);
|
methodParameters);
|
||||||
|
|
||||||
ILGenerator methodIL = methodBuilder.GetILGenerator();
|
ILGenerator methodIL = methodBuilder.GetILGenerator();
|
||||||
|
|
||||||
// invoke target: IProxyInvocationHandler
|
// invoke target: IProxyInvocationHandler
|
||||||
methodIL.Emit(OpCodes.Ldarg_0);
|
methodIL.Emit(OpCodes.Ldarg_0);
|
||||||
methodIL.Emit(OpCodes.Ldfld, handlerField);
|
methodIL.Emit(OpCodes.Ldfld, handlerField);
|
||||||
|
|
||||||
// 1st parameter: object proxy
|
// 1st parameter: object proxy
|
||||||
methodIL.Emit(OpCodes.Ldarg_0);
|
methodIL.Emit(OpCodes.Ldarg_0);
|
||||||
|
|
||||||
// 2nd parameter: MethodInfo method
|
// 2nd parameter: MethodInfo method
|
||||||
methodIL.Emit(OpCodes.Ldtoken, methodInfo);
|
methodIL.Emit(OpCodes.Ldtoken, methodInfo);
|
||||||
methodIL.Emit(OpCodes.Call, GetMethodFromHandleMethod);
|
methodIL.Emit(OpCodes.Call, GetMethodFromHandleMethod);
|
||||||
methodIL.Emit(OpCodes.Castclass, typeof(MethodInfo));
|
methodIL.Emit(OpCodes.Castclass, typeof(MethodInfo));
|
||||||
|
|
||||||
// 3rd parameter: object[] parameters
|
// 3rd parameter: object[] parameters
|
||||||
methodIL.Emit(OpCodes.Ldc_I4, numOfParams);
|
methodIL.Emit(OpCodes.Ldc_I4, numOfParams);
|
||||||
methodIL.Emit(OpCodes.Newarr, typeof(object));
|
methodIL.Emit(OpCodes.Newarr, typeof(object));
|
||||||
|
|
||||||
// if we have any parameters, then iterate through and set the values
|
// if we have any parameters, then iterate through and set the values
|
||||||
// of each element to the corresponding arguments
|
// 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); // copy the array
|
methodIL.Emit(OpCodes.Dup); // copy the array
|
||||||
methodIL.Emit(OpCodes.Ldc_I4, j);
|
methodIL.Emit(OpCodes.Ldc_I4, j);
|
||||||
methodIL.Emit(OpCodes.Ldarg, j + 1); // +1 for "this"
|
methodIL.Emit(OpCodes.Ldarg, j + 1); // +1 for "this"
|
||||||
if (methodParameters[j].IsValueType)
|
if (methodParameters[j].IsValueType)
|
||||||
{
|
{
|
||||||
methodIL.Emit(OpCodes.Box, methodParameters[j]);
|
methodIL.Emit(OpCodes.Box, methodParameters[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
methodIL.Emit(OpCodes.Stelem_Ref);
|
methodIL.Emit(OpCodes.Stelem_Ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
// call the Invoke method
|
// call the Invoke method
|
||||||
methodIL.Emit(OpCodes.Callvirt, InvokeMethod);
|
methodIL.Emit(OpCodes.Callvirt, InvokeMethod);
|
||||||
|
|
||||||
if (methodInfo.ReturnType != typeof(void))
|
if (methodInfo.ReturnType != typeof(void))
|
||||||
{
|
{
|
||||||
methodIL.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType);
|
methodIL.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// pop the return value that Invoke returned from the stack since
|
// pop the return value that Invoke returned from the stack since
|
||||||
// the method's return type is void.
|
// the method's return type is void.
|
||||||
methodIL.Emit(OpCodes.Pop);
|
methodIL.Emit(OpCodes.Pop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
methodIL.Emit(OpCodes.Ret);
|
methodIL.Emit(OpCodes.Ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through the parent interfaces and recursively call this method
|
// 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);
|
GenerateMethod(parentType, handlerField, typeBuilder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,11 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
|
||||||
namespace WinSW.Native
|
namespace WinSW.Native
|
||||||
{
|
{
|
||||||
internal static class Kernel32
|
internal static class Kernel32
|
||||||
{
|
{
|
||||||
[DllImport(Libraries.Kernel32)]
|
[DllImport(Libraries.Kernel32)]
|
||||||
internal static extern bool SetStdHandle(int stdHandle, SafeFileHandle handle);
|
internal static extern bool SetStdHandle(int stdHandle, SafeFileHandle handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,108 +1,108 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WinSW
|
namespace WinSW
|
||||||
{
|
{
|
||||||
// This is largely borrowed from the logback Rolling Calendar.
|
// This is largely borrowed from the logback Rolling Calendar.
|
||||||
public class PeriodicRollingCalendar
|
public class PeriodicRollingCalendar
|
||||||
{
|
{
|
||||||
private readonly string format;
|
private readonly string format;
|
||||||
private readonly long period;
|
private readonly long period;
|
||||||
private DateTime currentRoll;
|
private DateTime currentRoll;
|
||||||
private DateTime nextRoll;
|
private DateTime nextRoll;
|
||||||
|
|
||||||
public PeriodicRollingCalendar(string format, long period)
|
public PeriodicRollingCalendar(string format, long period)
|
||||||
{
|
{
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.period = period;
|
this.period = period;
|
||||||
this.currentRoll = DateTime.Now;
|
this.currentRoll = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
this.PeriodicityType = this.DeterminePeriodicityType();
|
this.PeriodicityType = this.DeterminePeriodicityType();
|
||||||
this.nextRoll = this.NextTriggeringTime(this.currentRoll, this.period);
|
this.nextRoll = this.NextTriggeringTime(this.currentRoll, this.period);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Periodicity
|
public enum Periodicity
|
||||||
{
|
{
|
||||||
ERRONEOUS,
|
ERRONEOUS,
|
||||||
TOP_OF_MILLISECOND,
|
TOP_OF_MILLISECOND,
|
||||||
TOP_OF_SECOND,
|
TOP_OF_SECOND,
|
||||||
TOP_OF_MINUTE,
|
TOP_OF_MINUTE,
|
||||||
TOP_OF_HOUR,
|
TOP_OF_HOUR,
|
||||||
TOP_OF_DAY
|
TOP_OF_DAY
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Periodicity[] ValidOrderedList =
|
private static readonly Periodicity[] ValidOrderedList =
|
||||||
{
|
{
|
||||||
Periodicity.TOP_OF_MILLISECOND, Periodicity.TOP_OF_SECOND, Periodicity.TOP_OF_MINUTE, Periodicity.TOP_OF_HOUR, Periodicity.TOP_OF_DAY
|
Periodicity.TOP_OF_MILLISECOND, Periodicity.TOP_OF_SECOND, Periodicity.TOP_OF_MINUTE, Periodicity.TOP_OF_HOUR, Periodicity.TOP_OF_DAY
|
||||||
};
|
};
|
||||||
|
|
||||||
private Periodicity DeterminePeriodicityType()
|
private Periodicity DeterminePeriodicityType()
|
||||||
{
|
{
|
||||||
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
|
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
|
||||||
DateTime epoch = new DateTime(1970, 1, 1);
|
DateTime epoch = new DateTime(1970, 1, 1);
|
||||||
|
|
||||||
foreach (Periodicity i in ValidOrderedList)
|
foreach (Periodicity i in ValidOrderedList)
|
||||||
{
|
{
|
||||||
string r0 = epoch.ToString(this.format);
|
string r0 = epoch.ToString(this.format);
|
||||||
periodicRollingCalendar.PeriodicityType = i;
|
periodicRollingCalendar.PeriodicityType = i;
|
||||||
|
|
||||||
DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
|
DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
|
||||||
string r1 = next.ToString(this.format);
|
string r1 = next.ToString(this.format);
|
||||||
|
|
||||||
if (r0 != r1)
|
if (r0 != r1)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Periodicity.ERRONEOUS;
|
return Periodicity.ERRONEOUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime NextTriggeringTime(DateTime input, long increment) => this.PeriodicityType switch
|
private DateTime NextTriggeringTime(DateTime input, long increment) => this.PeriodicityType switch
|
||||||
{
|
{
|
||||||
Periodicity.TOP_OF_MILLISECOND =>
|
Periodicity.TOP_OF_MILLISECOND =>
|
||||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond)
|
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond)
|
||||||
.AddMilliseconds(increment),
|
.AddMilliseconds(increment),
|
||||||
|
|
||||||
Periodicity.TOP_OF_SECOND =>
|
Periodicity.TOP_OF_SECOND =>
|
||||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)
|
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)
|
||||||
.AddSeconds(increment),
|
.AddSeconds(increment),
|
||||||
|
|
||||||
Periodicity.TOP_OF_MINUTE =>
|
Periodicity.TOP_OF_MINUTE =>
|
||||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)
|
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)
|
||||||
.AddMinutes(increment),
|
.AddMinutes(increment),
|
||||||
|
|
||||||
Periodicity.TOP_OF_HOUR =>
|
Periodicity.TOP_OF_HOUR =>
|
||||||
new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)
|
new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)
|
||||||
.AddHours(increment),
|
.AddHours(increment),
|
||||||
|
|
||||||
Periodicity.TOP_OF_DAY =>
|
Periodicity.TOP_OF_DAY =>
|
||||||
new DateTime(input.Year, input.Month, input.Day)
|
new DateTime(input.Year, input.Month, input.Day)
|
||||||
.AddDays(increment),
|
.AddDays(increment),
|
||||||
|
|
||||||
_ => throw new Exception("invalid periodicity type: " + this.PeriodicityType),
|
_ => throw new Exception("invalid periodicity type: " + this.PeriodicityType),
|
||||||
};
|
};
|
||||||
|
|
||||||
public Periodicity PeriodicityType { get; set; }
|
public Periodicity PeriodicityType { get; set; }
|
||||||
|
|
||||||
public bool ShouldRoll
|
public bool ShouldRoll
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
DateTime now = DateTime.Now;
|
DateTime now = DateTime.Now;
|
||||||
if (now > this.nextRoll)
|
if (now > this.nextRoll)
|
||||||
{
|
{
|
||||||
this.currentRoll = now;
|
this.currentRoll = now;
|
||||||
this.nextRoll = this.NextTriggeringTime(now, this.period);
|
this.nextRoll = this.NextTriggeringTime(now, this.period);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Format => this.currentRoll.ToString(this.format);
|
public string Format => this.currentRoll.ToString(this.format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,227 +1,227 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Management;
|
using System.Management;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using DynamicProxy;
|
using DynamicProxy;
|
||||||
|
|
||||||
namespace WMI
|
namespace WMI
|
||||||
{
|
{
|
||||||
// https://docs.microsoft.com/windows/win32/cimwin32prov/create-method-in-class-win32-service
|
// https://docs.microsoft.com/windows/win32/cimwin32prov/create-method-in-class-win32-service
|
||||||
public enum ReturnValue : uint
|
public enum ReturnValue : uint
|
||||||
{
|
{
|
||||||
Success = 0,
|
Success = 0,
|
||||||
NotSupported = 1,
|
NotSupported = 1,
|
||||||
AccessDenied = 2,
|
AccessDenied = 2,
|
||||||
DependentServicesRunning = 3,
|
DependentServicesRunning = 3,
|
||||||
InvalidServiceControl = 4,
|
InvalidServiceControl = 4,
|
||||||
ServiceCannotAcceptControl = 5,
|
ServiceCannotAcceptControl = 5,
|
||||||
ServiceNotActive = 6,
|
ServiceNotActive = 6,
|
||||||
ServiceRequestTimeout = 7,
|
ServiceRequestTimeout = 7,
|
||||||
UnknownFailure = 8,
|
UnknownFailure = 8,
|
||||||
PathNotFound = 9,
|
PathNotFound = 9,
|
||||||
ServiceAlreadyRunning = 10,
|
ServiceAlreadyRunning = 10,
|
||||||
ServiceDatabaseLocked = 11,
|
ServiceDatabaseLocked = 11,
|
||||||
ServiceDependencyDeleted = 12,
|
ServiceDependencyDeleted = 12,
|
||||||
ServiceDependencyFailure = 13,
|
ServiceDependencyFailure = 13,
|
||||||
ServiceDisabled = 14,
|
ServiceDisabled = 14,
|
||||||
ServiceLogonFailure = 15,
|
ServiceLogonFailure = 15,
|
||||||
ServiceMarkedForDeletion = 16,
|
ServiceMarkedForDeletion = 16,
|
||||||
ServiceNoThread = 17,
|
ServiceNoThread = 17,
|
||||||
StatusCircularDependency = 18,
|
StatusCircularDependency = 18,
|
||||||
StatusDuplicateName = 19,
|
StatusDuplicateName = 19,
|
||||||
StatusInvalidName = 20,
|
StatusInvalidName = 20,
|
||||||
StatusInvalidParameter = 21,
|
StatusInvalidParameter = 21,
|
||||||
StatusInvalidServiceAccount = 22,
|
StatusInvalidServiceAccount = 22,
|
||||||
StatusServiceExists = 23,
|
StatusServiceExists = 23,
|
||||||
ServiceAlreadyPaused = 24,
|
ServiceAlreadyPaused = 24,
|
||||||
|
|
||||||
NoSuchService = 200
|
NoSuchService = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signals a problem in WMI related operations
|
/// Signals a problem in WMI related operations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WmiException : Exception
|
public class WmiException : Exception
|
||||||
{
|
{
|
||||||
public readonly ReturnValue ErrorCode;
|
public readonly ReturnValue ErrorCode;
|
||||||
|
|
||||||
public WmiException(string message, ReturnValue code)
|
public WmiException(string message, ReturnValue code)
|
||||||
: base(message)
|
: base(message)
|
||||||
{
|
{
|
||||||
this.ErrorCode = code;
|
this.ErrorCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WmiException(ReturnValue code)
|
public WmiException(ReturnValue code)
|
||||||
: this(code.ToString(), code)
|
: this(code.ToString(), code)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Associated a WMI class name to the proxy interface (which should extend from IWmiCollection)
|
/// Associated a WMI class name to the proxy interface (which should extend from IWmiCollection)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WmiClassName : Attribute
|
public class WmiClassName : Attribute
|
||||||
{
|
{
|
||||||
public readonly string Name;
|
public readonly string Name;
|
||||||
|
|
||||||
public WmiClassName(string name) => this.Name = name;
|
public WmiClassName(string name) => this.Name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marker interface to denote a collection in WMI.
|
/// Marker interface to denote a collection in WMI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWmiCollection
|
public interface IWmiCollection
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marker interface to denote an individual managed object
|
/// Marker interface to denote an individual managed object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWmiObject
|
public interface IWmiObject
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class WmiRoot
|
public sealed class WmiRoot
|
||||||
{
|
{
|
||||||
private readonly ManagementScope wmiScope;
|
private readonly ManagementScope wmiScope;
|
||||||
|
|
||||||
public WmiRoot()
|
public WmiRoot()
|
||||||
{
|
{
|
||||||
ConnectionOptions options = new ConnectionOptions
|
ConnectionOptions options = new ConnectionOptions
|
||||||
{
|
{
|
||||||
EnablePrivileges = true,
|
EnablePrivileges = true,
|
||||||
Impersonation = ImpersonationLevel.Impersonate,
|
Impersonation = ImpersonationLevel.Impersonate,
|
||||||
Authentication = AuthenticationLevel.PacketPrivacy,
|
Authentication = AuthenticationLevel.PacketPrivacy,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.wmiScope = new ManagementScope(@"\\.\root\cimv2", options);
|
this.wmiScope = new ManagementScope(@"\\.\root\cimv2", options);
|
||||||
this.wmiScope.Connect();
|
this.wmiScope.Connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string Capitalize(string s)
|
private static string Capitalize(string s)
|
||||||
{
|
{
|
||||||
return char.ToUpper(s[0]) + s.Substring(1);
|
return char.ToUpper(s[0]) + s.Substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class BaseHandler : IProxyInvocationHandler
|
private abstract class BaseHandler : IProxyInvocationHandler
|
||||||
{
|
{
|
||||||
public abstract object? Invoke(object proxy, MethodInfo method, object[] arguments);
|
public abstract object? Invoke(object proxy, MethodInfo method, object[] arguments);
|
||||||
|
|
||||||
protected void CheckError(ManagementBaseObject result)
|
protected void CheckError(ManagementBaseObject result)
|
||||||
{
|
{
|
||||||
uint code = (uint)result["returnValue"];
|
uint code = (uint)result["returnValue"];
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
{
|
{
|
||||||
throw new WmiException((ReturnValue)code);
|
throw new WmiException((ReturnValue)code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ManagementBaseObject GetMethodParameters(ManagementObject wmiObject, string methodName, ParameterInfo[] methodParameters, object[] arguments)
|
protected ManagementBaseObject GetMethodParameters(ManagementObject wmiObject, string methodName, ParameterInfo[] methodParameters, object[] arguments)
|
||||||
{
|
{
|
||||||
ManagementBaseObject wmiParameters = wmiObject.GetMethodParameters(methodName);
|
ManagementBaseObject wmiParameters = wmiObject.GetMethodParameters(methodName);
|
||||||
for (int i = 0; i < arguments.Length; i++)
|
for (int i = 0; i < arguments.Length; i++)
|
||||||
{
|
{
|
||||||
string capitalizedName = Capitalize(methodParameters[i].Name!);
|
string capitalizedName = Capitalize(methodParameters[i].Name!);
|
||||||
wmiParameters[capitalizedName] = arguments[i];
|
wmiParameters[capitalizedName] = arguments[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return wmiParameters;
|
return wmiParameters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InstanceHandler : BaseHandler, IWmiObject
|
private class InstanceHandler : BaseHandler, IWmiObject
|
||||||
{
|
{
|
||||||
private readonly ManagementObject wmiObject;
|
private readonly ManagementObject wmiObject;
|
||||||
|
|
||||||
public InstanceHandler(ManagementObject wmiObject) => this.wmiObject = wmiObject;
|
public InstanceHandler(ManagementObject wmiObject) => this.wmiObject = wmiObject;
|
||||||
|
|
||||||
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
|
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
|
||||||
{
|
{
|
||||||
if (method.DeclaringType == typeof(IWmiObject))
|
if (method.DeclaringType == typeof(IWmiObject))
|
||||||
{
|
{
|
||||||
return method.Invoke(this, arguments);
|
return method.Invoke(this, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: proper property support
|
// TODO: proper property support
|
||||||
if (method.Name.StartsWith("set_"))
|
if (method.Name.StartsWith("set_"))
|
||||||
{
|
{
|
||||||
this.wmiObject[method.Name.Substring(4)] = arguments[0];
|
this.wmiObject[method.Name.Substring(4)] = arguments[0];
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method.Name.StartsWith("get_"))
|
if (method.Name.StartsWith("get_"))
|
||||||
{
|
{
|
||||||
return this.wmiObject[method.Name.Substring(4)];
|
return this.wmiObject[method.Name.Substring(4)];
|
||||||
}
|
}
|
||||||
|
|
||||||
string methodName = method.Name;
|
string methodName = method.Name;
|
||||||
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
|
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
|
||||||
this.GetMethodParameters(this.wmiObject, methodName, method.GetParameters(), arguments);
|
this.GetMethodParameters(this.wmiObject, methodName, method.GetParameters(), arguments);
|
||||||
using ManagementBaseObject result = this.wmiObject.InvokeMethod(methodName, wmiParameters, null);
|
using ManagementBaseObject result = this.wmiObject.InvokeMethod(methodName, wmiParameters, null);
|
||||||
this.CheckError(result);
|
this.CheckError(result);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ClassHandler : BaseHandler
|
private class ClassHandler : BaseHandler
|
||||||
{
|
{
|
||||||
private readonly ManagementClass wmiClass;
|
private readonly ManagementClass wmiClass;
|
||||||
private readonly string className;
|
private readonly string className;
|
||||||
|
|
||||||
public ClassHandler(ManagementScope wmiScope, string className)
|
public ClassHandler(ManagementScope wmiScope, string className)
|
||||||
{
|
{
|
||||||
this.wmiClass = new ManagementClass(wmiScope, new ManagementPath(className), null);
|
this.wmiClass = new ManagementClass(wmiScope, new ManagementPath(className), null);
|
||||||
this.className = className;
|
this.className = className;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
|
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
|
||||||
{
|
{
|
||||||
ParameterInfo[] methodParameters = method.GetParameters();
|
ParameterInfo[] methodParameters = method.GetParameters();
|
||||||
|
|
||||||
if (method.Name == nameof(IWin32Services.Select))
|
if (method.Name == nameof(IWin32Services.Select))
|
||||||
{
|
{
|
||||||
// select method to find instances
|
// select method to find instances
|
||||||
StringBuilder query = new StringBuilder("SELECT * FROM ").Append(this.className).Append(" WHERE ");
|
StringBuilder query = new StringBuilder("SELECT * FROM ").Append(this.className).Append(" WHERE ");
|
||||||
for (int i = 0; i < arguments.Length; i++)
|
for (int i = 0; i < arguments.Length; i++)
|
||||||
{
|
{
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
{
|
{
|
||||||
query.Append(" AND ");
|
query.Append(" AND ");
|
||||||
}
|
}
|
||||||
|
|
||||||
query.Append(' ').Append(Capitalize(methodParameters[i].Name!)).Append(" = '").Append(arguments[i]).Append('\'');
|
query.Append(' ').Append(Capitalize(methodParameters[i].Name!)).Append(" = '").Append(arguments[i]).Append('\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
using ManagementObjectSearcher searcher = new ManagementObjectSearcher(this.wmiClass.Scope, new ObjectQuery(query.ToString()));
|
using ManagementObjectSearcher searcher = new ManagementObjectSearcher(this.wmiClass.Scope, new ObjectQuery(query.ToString()));
|
||||||
using ManagementObjectCollection results = searcher.Get();
|
using ManagementObjectCollection results = searcher.Get();
|
||||||
|
|
||||||
// TODO: support collections
|
// TODO: support collections
|
||||||
foreach (ManagementObject wmiObject in results)
|
foreach (ManagementObject wmiObject in results)
|
||||||
{
|
{
|
||||||
return ProxyFactory.Create(new InstanceHandler(wmiObject), method.ReturnType, true);
|
return ProxyFactory.Create(new InstanceHandler(wmiObject), method.ReturnType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
string methodName = method.Name;
|
string methodName = method.Name;
|
||||||
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
|
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
|
||||||
this.GetMethodParameters(this.wmiClass, methodName, methodParameters, arguments);
|
this.GetMethodParameters(this.wmiClass, methodName, methodParameters, arguments);
|
||||||
using ManagementBaseObject result = this.wmiClass.InvokeMethod(methodName, wmiParameters, null);
|
using ManagementBaseObject result = this.wmiClass.InvokeMethod(methodName, wmiParameters, null);
|
||||||
this.CheckError(result);
|
this.CheckError(result);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Obtains an object that corresponds to a table in WMI, which is a collection of a managed object.
|
/// Obtains an object that corresponds to a table in WMI, which is a collection of a managed object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T GetCollection<T>()
|
public T GetCollection<T>()
|
||||||
where T : IWmiCollection
|
where T : IWmiCollection
|
||||||
{
|
{
|
||||||
WmiClassName className = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
|
WmiClassName className = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
|
||||||
|
|
||||||
return (T)ProxyFactory.Create(new ClassHandler(this.wmiScope, className.Name), typeof(T), true);
|
return (T)ProxyFactory.Create(new ClassHandler(this.wmiScope, className.Name), typeof(T), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +1,72 @@
|
||||||
namespace WMI
|
namespace WMI
|
||||||
{
|
{
|
||||||
public enum ServiceType
|
public enum ServiceType
|
||||||
{
|
{
|
||||||
KernalDriver = 1,
|
KernalDriver = 1,
|
||||||
FileSystemDriver = 2,
|
FileSystemDriver = 2,
|
||||||
Adapter = 4,
|
Adapter = 4,
|
||||||
RecognizerDriver = 8,
|
RecognizerDriver = 8,
|
||||||
OwnProcess = 16,
|
OwnProcess = 16,
|
||||||
ShareProcess = 32,
|
ShareProcess = 32,
|
||||||
InteractiveProcess = 256,
|
InteractiveProcess = 256,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ErrorControl
|
public enum ErrorControl
|
||||||
{
|
{
|
||||||
UserNotNotified = 0,
|
UserNotNotified = 0,
|
||||||
UserNotified = 1,
|
UserNotified = 1,
|
||||||
SystemRestartedWithLastKnownGoodConfiguration = 2,
|
SystemRestartedWithLastKnownGoodConfiguration = 2,
|
||||||
SystemAttemptsToStartWithAGoodConfiguration = 3
|
SystemAttemptsToStartWithAGoodConfiguration = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum StartMode
|
public enum StartMode
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Device driver started by the operating system loader. This value is valid only for driver services.
|
/// Device driver started by the operating system loader. This value is valid only for driver services.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Boot,
|
Boot,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Device driver started by the operating system initialization process. This value is valid only for driver services.
|
/// Device driver started by the operating system initialization process. This value is valid only for driver services.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
System,
|
System,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Service to be started automatically by the Service Control Manager during system startup.
|
/// Service to be started automatically by the Service Control Manager during system startup.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Automatic,
|
Automatic,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Service to be started by the Service Control Manager when a process calls the StartService method.
|
/// Service to be started by the Service Control Manager when a process calls the StartService method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Manual,
|
Manual,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Service that can no longer be started.
|
/// Service that can no longer be started.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Disabled,
|
Disabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
[WmiClassName("Win32_Service")]
|
[WmiClassName("Win32_Service")]
|
||||||
public interface IWin32Services : IWmiCollection
|
public interface IWin32Services : IWmiCollection
|
||||||
{
|
{
|
||||||
// ReturnValue Create(bool desktopInteract, string displayName, int errorControl, string loadOrderGroup, string loadOrderGroupDependencies, string name, string pathName, string serviceDependencies, string serviceType, string startMode, string startName, string startPassword);
|
// ReturnValue Create(bool desktopInteract, string displayName, int errorControl, string loadOrderGroup, string loadOrderGroupDependencies, string name, string pathName, string serviceDependencies, string serviceType, string startMode, string startName, string startPassword);
|
||||||
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, string startMode, bool desktopInteract, string? startName, string? startPassword, string[] serviceDependencies);
|
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, string startMode, bool desktopInteract, string? startName, string? startPassword, string[] serviceDependencies);
|
||||||
|
|
||||||
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, string startMode, bool desktopInteract, string[] serviceDependencies);
|
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, string startMode, bool desktopInteract, string[] serviceDependencies);
|
||||||
|
|
||||||
IWin32Service? Select(string name);
|
IWin32Service? Select(string name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://docs.microsoft.com/windows/win32/cimwin32prov/win32-service
|
// https://docs.microsoft.com/windows/win32/cimwin32prov/win32-service
|
||||||
public interface IWin32Service : IWmiObject
|
public interface IWin32Service : IWmiObject
|
||||||
{
|
{
|
||||||
bool Started { get; }
|
bool Started { get; }
|
||||||
|
|
||||||
void Delete();
|
void Delete();
|
||||||
|
|
||||||
void StartService();
|
void StartService();
|
||||||
|
|
||||||
void StopService();
|
void StopService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
174
src/winsw.sln
174
src/winsw.sln
|
@ -1,87 +1,87 @@
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2013
|
# Visual Studio 2013
|
||||||
VisualStudioVersion = 12.0.31101.0
|
VisualStudioVersion = 12.0.31101.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winsw", "Core\ServiceWrapper\winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winsw", "Core\ServiceWrapper\winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winswTests", "Test\winswTests\winswTests.csproj", "{93843402-842B-44B4-B303-AEE829BE0B43}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winswTests", "Test\winswTests\winswTests.csproj", "{93843402-842B-44B4-B303-AEE829BE0B43}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedDirectoryMapper", "Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj", "{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedDirectoryMapper", "Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj", "{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{077C2CEC-B687-4B53-86E9-C1A1BF5554E5}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{077C2CEC-B687-4B53-86E9-C1A1BF5554E5}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{BC4AD891-E87E-4F30-867C-FD8084A29E5D}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{BC4AD891-E87E-4F30-867C-FD8084A29E5D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5297623A-1A95-4F89-9AAE-DA634081EC86}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5297623A-1A95-4F89-9AAE-DA634081EC86}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinSWCore", "Core\WinSWCore\WinSWCore.csproj", "{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinSWCore", "Core\WinSWCore\WinSWCore.csproj", "{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunawayProcessKiller", "Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj", "{57284B7A-82A4-407A-B706-EBEA6BF8EA13}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunawayProcessKiller", "Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj", "{57284B7A-82A4-407A-B706-EBEA6BF8EA13}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AA414F46-B863-473A-A0E0-C2971B3396AE}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AA414F46-B863-473A-A0E0-C2971B3396AE}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
..\examples\sample-allOptions.xml = ..\examples\sample-allOptions.xml
|
..\examples\sample-allOptions.xml = ..\examples\sample-allOptions.xml
|
||||||
..\examples\sample-minimal.xml = ..\examples\sample-minimal.xml
|
..\examples\sample-minimal.xml = ..\examples\sample-minimal.xml
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|Win32 = Release|Win32
|
Release|Win32 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{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|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.ActiveCfg = Debug|Any CPU
|
||||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Win32.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Debug|Win32.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{93843402-842B-44B4-B303-AEE829BE0B43}.Release|Win32.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Debug|Win32.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Debug|Win32.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Win32.Build.0 = Release|Any CPU
|
{57284B7A-82A4-407A-B706-EBEA6BF8EA13}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{0DE77F55-ADE5-43C1-999A-0BC81153B039} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
|
||||||
{93843402-842B-44B4-B303-AEE829BE0B43} = {077C2CEC-B687-4B53-86E9-C1A1BF5554E5}
|
{93843402-842B-44B4-B303-AEE829BE0B43} = {077C2CEC-B687-4B53-86E9-C1A1BF5554E5}
|
||||||
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
|
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
|
||||||
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
|
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
|
||||||
{57284B7A-82A4-407A-B706-EBEA6BF8EA13} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
|
{57284B7A-82A4-407A-B706-EBEA6BF8EA13} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
Loading…
Reference in New Issue