mirror of https://github.com/winsw/winsw
Annotate WinSWCore for nullable reference types
parent
d10f3b8ccf
commit
5be8708701
|
@ -402,7 +402,7 @@ namespace winsw
|
||||||
private void StartProcess(Process processToStart, string arguments, string executable, LogHandler logHandler, bool redirectStdin)
|
private void StartProcess(Process processToStart, string arguments, string executable, LogHandler logHandler, bool redirectStdin)
|
||||||
{
|
{
|
||||||
// Define handler of the completed process
|
// Define handler of the completed process
|
||||||
ProcessCompletionCallback processCompletionCallback = proc =>
|
void OnProcessCompleted(Process proc)
|
||||||
{
|
{
|
||||||
string msg = processToStart.Id + " - " + processToStart.StartInfo.FileName + " " + processToStart.StartInfo.Arguments;
|
string msg = processToStart.Id + " - " + processToStart.StartInfo.FileName + " " + processToStart.StartInfo.Arguments;
|
||||||
try
|
try
|
||||||
|
@ -427,16 +427,11 @@ namespace winsw
|
||||||
{
|
{
|
||||||
LogEvent("WaitForExit " + ioe.Message);
|
LogEvent("WaitForExit " + ioe.Message);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
try
|
|
||||||
{
|
{
|
||||||
proc.Dispose();
|
proc.Dispose();
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ioe)
|
}
|
||||||
{
|
|
||||||
LogEvent("Dispose " + ioe.Message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invoke process and exit
|
// Invoke process and exit
|
||||||
ProcessHelper.StartProcessAndCallbackForExit(
|
ProcessHelper.StartProcessAndCallbackForExit(
|
||||||
|
@ -446,7 +441,7 @@ namespace winsw
|
||||||
envVars: _envs,
|
envVars: _envs,
|
||||||
workingDirectory: _descriptor.WorkingDirectory,
|
workingDirectory: _descriptor.WorkingDirectory,
|
||||||
priority: _descriptor.Priority,
|
priority: _descriptor.Priority,
|
||||||
callback: processCompletionCallback,
|
callback: OnProcessCompleted,
|
||||||
logHandler: logHandler,
|
logHandler: logHandler,
|
||||||
redirectStdin: redirectStdin,
|
redirectStdin: redirectStdin,
|
||||||
hideWindow: _descriptor.HideWindow);
|
hideWindow: _descriptor.HideWindow);
|
||||||
|
@ -712,8 +707,7 @@ namespace winsw
|
||||||
// run restart from another process group. see README.md for why this is useful.
|
// run restart from another process group. see README.md for why this is useful.
|
||||||
|
|
||||||
STARTUPINFO si = default;
|
STARTUPINFO si = default;
|
||||||
|
bool result = Kernel32.CreateProcess(null, d.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200/*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out _);
|
||||||
bool result = Kernel32.CreateProcess(null, d.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200/*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out PROCESS_INFORMATION pi);
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
|
throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
|
||||||
|
@ -731,6 +725,7 @@ namespace winsw
|
||||||
Console.WriteLine("Started");
|
Console.WriteLine("Started");
|
||||||
else
|
else
|
||||||
Console.WriteLine("Stopped");
|
Console.WriteLine("Stopped");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,30 +19,23 @@ namespace winsw.Configuration
|
||||||
public string Executable => null;
|
public string Executable => null;
|
||||||
public bool HideWindow => false;
|
public bool HideWindow => false;
|
||||||
|
|
||||||
public string ExecutablePath
|
// this returns the executable name as given by the calling process, so
|
||||||
{
|
// it needs to be absolutized.
|
||||||
get
|
public string ExecutablePath => Path.GetFullPath(Environment.GetCommandLineArgs()[0]);
|
||||||
{
|
|
||||||
// this returns the executable name as given by the calling process, so
|
|
||||||
// it needs to be absolutized.
|
|
||||||
string p = Environment.GetCommandLineArgs()[0];
|
|
||||||
return Path.GetFullPath(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Installation
|
// Installation
|
||||||
public bool AllowServiceAcountLogonRight => false;
|
public bool AllowServiceAcountLogonRight => false;
|
||||||
public string ServiceAccountPassword => null;
|
public string? ServiceAccountPassword => null;
|
||||||
public string ServiceAccountUser => "NULL\\NULL";
|
public string ServiceAccountUser => "NULL\\NULL";
|
||||||
public List<Native.SC_ACTION> FailureActions => new List<Native.SC_ACTION>();
|
public List<Native.SC_ACTION> FailureActions => new List<Native.SC_ACTION>();
|
||||||
public TimeSpan ResetFailureAfter => TimeSpan.FromDays(1);
|
public TimeSpan ResetFailureAfter => TimeSpan.FromDays(1);
|
||||||
|
|
||||||
// Executable management
|
// Executable management
|
||||||
public string Arguments => string.Empty;
|
public string Arguments => string.Empty;
|
||||||
public string Startarguments => null;
|
public string? Startarguments => null;
|
||||||
public string StopExecutable => null;
|
public string? StopExecutable => null;
|
||||||
public string Stoparguments => null;
|
public string? Stoparguments => null;
|
||||||
public string WorkingDirectory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
public string WorkingDirectory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||||
public ProcessPriorityClass Priority => ProcessPriorityClass.Normal;
|
public ProcessPriorityClass Priority => ProcessPriorityClass.Normal;
|
||||||
public TimeSpan StopTimeout => TimeSpan.FromSeconds(15);
|
public TimeSpan StopTimeout => TimeSpan.FromSeconds(15);
|
||||||
public bool StopParentProcessFirst => false;
|
public bool StopParentProcessFirst => false;
|
||||||
|
@ -56,7 +49,7 @@ namespace winsw.Configuration
|
||||||
public bool Interactive => false;
|
public bool Interactive => false;
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
public string LogDirectory => Path.GetDirectoryName(ExecutablePath);
|
public string LogDirectory => Path.GetDirectoryName(ExecutablePath)!;
|
||||||
public string LogMode => "append";
|
public string LogMode => "append";
|
||||||
|
|
||||||
public bool OutFileDisabled => false;
|
public bool OutFileDisabled => false;
|
||||||
|
@ -72,6 +65,6 @@ namespace winsw.Configuration
|
||||||
public bool BeepOnShutdown => false;
|
public bool BeepOnShutdown => false;
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
public XmlNode ExtensionsConfiguration => null;
|
public XmlNode? ExtensionsConfiguration => null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using WMI;
|
using WMI;
|
||||||
|
|
||||||
namespace winsw.Configuration
|
namespace winsw.Configuration
|
||||||
{
|
{
|
||||||
public interface IWinSWConfiguration
|
public interface IWinSWConfiguration
|
||||||
|
@ -18,16 +19,16 @@ namespace winsw.Configuration
|
||||||
|
|
||||||
// Installation
|
// Installation
|
||||||
bool AllowServiceAcountLogonRight { get; }
|
bool AllowServiceAcountLogonRight { get; }
|
||||||
string ServiceAccountPassword { get; }
|
string? ServiceAccountPassword { get; }
|
||||||
string ServiceAccountUser { get; }
|
string ServiceAccountUser { get; }
|
||||||
List<Native.SC_ACTION> FailureActions { get; }
|
List<Native.SC_ACTION> FailureActions { get; }
|
||||||
TimeSpan ResetFailureAfter { get; }
|
TimeSpan ResetFailureAfter { get; }
|
||||||
|
|
||||||
// Executable management
|
// Executable management
|
||||||
string Arguments { get; }
|
string Arguments { get; }
|
||||||
string Startarguments { get; }
|
string? Startarguments { get; }
|
||||||
string StopExecutable { get; }
|
string? StopExecutable { get; }
|
||||||
string Stoparguments { get; }
|
string? Stoparguments { get; }
|
||||||
string WorkingDirectory { get; }
|
string WorkingDirectory { get; }
|
||||||
ProcessPriorityClass Priority { get; }
|
ProcessPriorityClass Priority { get; }
|
||||||
TimeSpan StopTimeout { get; }
|
TimeSpan StopTimeout { get; }
|
||||||
|
@ -53,6 +54,6 @@ namespace winsw.Configuration
|
||||||
bool BeepOnShutdown { get; }
|
bool BeepOnShutdown { get; }
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
XmlNode ExtensionsConfiguration { get; }
|
XmlNode? ExtensionsConfiguration { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,20 +23,21 @@ namespace winsw
|
||||||
public readonly string From;
|
public readonly string From;
|
||||||
public readonly string To;
|
public readonly string To;
|
||||||
public readonly AuthType Auth = AuthType.none;
|
public readonly AuthType Auth = AuthType.none;
|
||||||
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 string ShortId => $"(download from {From})";
|
public string ShortId => $"(download from {From})";
|
||||||
|
|
||||||
|
// 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)
|
||||||
{
|
{
|
||||||
From = from;
|
From = from;
|
||||||
|
@ -119,7 +120,7 @@ namespace winsw
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AuthType.basic:
|
case AuthType.basic:
|
||||||
SetBasicAuthHeader(req, Username, Password);
|
SetBasicAuthHeader(req, Username!, Password!);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ namespace DynamicProxy
|
||||||
/// <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>
|
||||||
|
@ -23,7 +23,7 @@ namespace DynamicProxy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MetaDataFactory
|
public class MetaDataFactory
|
||||||
{
|
{
|
||||||
private static Hashtable typeMap = new Hashtable();
|
private static readonly Dictionary<string, Type> typeMap = new Dictionary<string, Type>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class constructor. Private because this is a static class.
|
/// Class constructor. Private because this is a static class.
|
||||||
|
@ -41,12 +41,16 @@ namespace DynamicProxy
|
||||||
{
|
{
|
||||||
if (interfaceType != null)
|
if (interfaceType != null)
|
||||||
{
|
{
|
||||||
lock (typeMap.SyncRoot)
|
lock (typeMap)
|
||||||
{
|
{
|
||||||
if (!typeMap.ContainsKey(interfaceType.FullName))
|
#if NETCOREAPP
|
||||||
|
_ = typeMap.TryAdd(interfaceType.FullName!, interfaceType);
|
||||||
|
#else
|
||||||
|
if (!typeMap.ContainsKey(interfaceType.FullName!))
|
||||||
{
|
{
|
||||||
typeMap.Add(interfaceType.FullName, interfaceType);
|
typeMap.Add(interfaceType.FullName!, interfaceType);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,10 +63,10 @@ namespace DynamicProxy
|
||||||
///<returns>MethodInfo</returns>
|
///<returns>MethodInfo</returns>
|
||||||
public static MethodInfo GetMethod(string name, int i)
|
public static MethodInfo GetMethod(string name, int i)
|
||||||
{
|
{
|
||||||
Type type = null;
|
Type? type = null;
|
||||||
lock (typeMap.SyncRoot)
|
lock (typeMap)
|
||||||
{
|
{
|
||||||
type = (Type)typeMap[name];
|
type = typeMap[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
return type.GetMethods()[i];
|
return type.GetMethods()[i];
|
||||||
|
@ -70,10 +74,10 @@ namespace DynamicProxy
|
||||||
|
|
||||||
public static PropertyInfo GetProperty(string name, int i)
|
public static PropertyInfo GetProperty(string name, int i)
|
||||||
{
|
{
|
||||||
Type type = null;
|
Type? type = null;
|
||||||
lock (typeMap.SyncRoot)
|
lock (typeMap)
|
||||||
{
|
{
|
||||||
type = (Type)typeMap[name];
|
type = typeMap[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
return type.GetProperties()[i];
|
return type.GetProperties()[i];
|
||||||
|
@ -84,30 +88,27 @@ namespace DynamicProxy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ProxyFactory
|
public class ProxyFactory
|
||||||
{
|
{
|
||||||
private static ProxyFactory _instance;
|
private static ProxyFactory? _instance;
|
||||||
private static readonly object LockObj = new object();
|
private static readonly object LockObj = new object();
|
||||||
|
|
||||||
private readonly Hashtable _typeMap = Hashtable.Synchronized(new Hashtable());
|
private readonly Dictionary<string, Type> _typeMap = new Dictionary<string, Type>();
|
||||||
private static readonly Hashtable OpCodeTypeMapper = new Hashtable();
|
|
||||||
|
|
||||||
private const string PROXY_SUFFIX = "Proxy";
|
private static readonly Dictionary<Type, OpCode> OpCodeTypeMapper = new Dictionary<Type, OpCode>
|
||||||
private const string ASSEMBLY_NAME = "ProxyAssembly";
|
|
||||||
private const string MODULE_NAME = "ProxyModule";
|
|
||||||
private const string HANDLER_NAME = "handler";
|
|
||||||
|
|
||||||
// Initialize the value type mapper. This is needed for methods with intrinsic
|
|
||||||
// return types, used in the Emit process.
|
|
||||||
static ProxyFactory()
|
|
||||||
{
|
{
|
||||||
OpCodeTypeMapper.Add(typeof(bool), OpCodes.Ldind_I1);
|
{ typeof(bool), OpCodes.Ldind_I1 },
|
||||||
OpCodeTypeMapper.Add(typeof(short), OpCodes.Ldind_I2);
|
{ typeof(short), OpCodes.Ldind_I2 },
|
||||||
OpCodeTypeMapper.Add(typeof(int), OpCodes.Ldind_I4);
|
{ typeof(int), OpCodes.Ldind_I4 },
|
||||||
OpCodeTypeMapper.Add(typeof(long), OpCodes.Ldind_I8);
|
{ typeof(long), OpCodes.Ldind_I8 },
|
||||||
OpCodeTypeMapper.Add(typeof(double), OpCodes.Ldind_R8);
|
{ typeof(double), OpCodes.Ldind_R8 },
|
||||||
OpCodeTypeMapper.Add(typeof(float), OpCodes.Ldind_R4);
|
{ typeof(float), OpCodes.Ldind_R4 },
|
||||||
OpCodeTypeMapper.Add(typeof(ushort), OpCodes.Ldind_U2);
|
{ typeof(ushort), OpCodes.Ldind_U2 },
|
||||||
OpCodeTypeMapper.Add(typeof(uint), OpCodes.Ldind_U4);
|
{ typeof(uint), OpCodes.Ldind_U4 },
|
||||||
}
|
};
|
||||||
|
|
||||||
|
private const string ProxySuffix = "Proxy";
|
||||||
|
private const string AssemblyName = "ProxyAssembly";
|
||||||
|
private const string ModuleName = "ProxyModule";
|
||||||
|
private const string HandlerName = "handler";
|
||||||
|
|
||||||
private ProxyFactory()
|
private ProxyFactory()
|
||||||
{
|
{
|
||||||
|
@ -120,24 +121,25 @@ namespace DynamicProxy
|
||||||
CreateInstance();
|
CreateInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _instance;
|
return _instance!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateInstance()
|
private static void CreateInstance()
|
||||||
{
|
{
|
||||||
lock (LockObj)
|
lock (LockObj)
|
||||||
{
|
{
|
||||||
if (_instance == null)
|
_instance ??= new ProxyFactory();
|
||||||
{
|
|
||||||
_instance = new ProxyFactory();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Create(IProxyInvocationHandler handler, Type objType, bool isObjInterface)
|
public object Create(IProxyInvocationHandler handler, Type objType, bool isObjInterface)
|
||||||
{
|
{
|
||||||
string typeName = objType.FullName + PROXY_SUFFIX;
|
string typeName = objType.FullName + ProxySuffix;
|
||||||
Type type = (Type)_typeMap[typeName];
|
Type? type = null;
|
||||||
|
lock (_typeMap)
|
||||||
|
{
|
||||||
|
_ = _typeMap.TryGetValue(typeName, out type);
|
||||||
|
}
|
||||||
|
|
||||||
// check to see if the type was in the cache. If the type was not cached, then
|
// check to see if the type was in the cache. If the type was not cached, then
|
||||||
// create a new instance of the dynamic type and add it to the cache.
|
// create a new instance of the dynamic type and add it to the cache.
|
||||||
|
@ -152,11 +154,14 @@ namespace DynamicProxy
|
||||||
type = CreateType(handler, objType.GetInterfaces(), typeName);
|
type = CreateType(handler, objType.GetInterfaces(), typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
_typeMap.Add(typeName, type);
|
lock (_typeMap)
|
||||||
|
{
|
||||||
|
_typeMap.Add(typeName, type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return a new instance of the type.
|
// return a new instance of the type.
|
||||||
return Activator.CreateInstance(type, new object[] { handler });
|
return Activator.CreateInstance(type, new object[] { handler })!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Create(IProxyInvocationHandler handler, Type objType)
|
public object Create(IProxyInvocationHandler handler, Type objType)
|
||||||
|
@ -166,88 +171,78 @@ namespace DynamicProxy
|
||||||
|
|
||||||
private Type CreateType(IProxyInvocationHandler handler, Type[] interfaces, string dynamicTypeName)
|
private Type CreateType(IProxyInvocationHandler handler, Type[] interfaces, string dynamicTypeName)
|
||||||
{
|
{
|
||||||
Type retVal = null;
|
Type objType = typeof(object);
|
||||||
|
Type handlerType = typeof(IProxyInvocationHandler);
|
||||||
|
|
||||||
if (handler != null && interfaces != null)
|
AssemblyName assemblyName = new AssemblyName();
|
||||||
{
|
assemblyName.Name = AssemblyName;
|
||||||
Type objType = typeof(object);
|
assemblyName.Version = new Version(1, 0, 0, 0);
|
||||||
Type handlerType = typeof(IProxyInvocationHandler);
|
|
||||||
|
|
||||||
AssemblyName assemblyName = new AssemblyName();
|
// create a new assembly for this proxy, one that isn't presisted on the file system
|
||||||
assemblyName.Name = ASSEMBLY_NAME;
|
AssemblyBuilder assemblyBuilder =
|
||||||
assemblyName.Version = new Version(1, 0, 0, 0);
|
|
||||||
|
|
||||||
// create a new assembly for this proxy, one that isn't presisted on the file system
|
|
||||||
AssemblyBuilder assemblyBuilder =
|
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
AssemblyBuilder.DefineDynamicAssembly(
|
AssemblyBuilder.DefineDynamicAssembly(
|
||||||
#else
|
#else
|
||||||
AppDomain.CurrentDomain.DefineDynamicAssembly(
|
AppDomain.CurrentDomain.DefineDynamicAssembly(
|
||||||
#endif
|
#endif
|
||||||
assemblyName, AssemblyBuilderAccess.Run);
|
assemblyName, AssemblyBuilderAccess.Run);
|
||||||
|
|
||||||
// create a new module for this proxy
|
// create a new module for this proxy
|
||||||
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(MODULE_NAME);
|
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(ModuleName);
|
||||||
|
|
||||||
// Set the class to be public and sealed
|
// Set the class to be public and sealed
|
||||||
TypeAttributes typeAttributes =
|
TypeAttributes typeAttributes =
|
||||||
TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
|
TypeAttributes.Class | 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(
|
||||||
HANDLER_NAME, handlerType, FieldAttributes.Private);
|
HandlerName, handlerType, FieldAttributes.Private);
|
||||||
|
|
||||||
// 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 defaultObjConstructor = objType.GetConstructor( new Type[0] );
|
ConstructorInfo baseConstructor = objType.GetConstructor(Type.EmptyTypes)!;
|
||||||
ConstructorInfo superConstructor = objType.GetConstructor(new Type[0]);
|
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
|
||||||
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
|
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
|
||||||
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
|
|
||||||
|
|
||||||
#region( "Constructor IL Code" )
|
#region( "Constructor IL Code" )
|
||||||
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, superConstructor);
|
constructorIL.Emit(OpCodes.Call, baseConstructor);
|
||||||
// Constructor return
|
// Constructor return
|
||||||
constructorIL.Emit(OpCodes.Ret);
|
constructorIL.Emit(OpCodes.Ret);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
|
||||||
|
|
||||||
retVal = typeBuilder.CreateType();
|
|
||||||
|
|
||||||
// assemblyBuilder.Save(dynamicTypeName + ".dll");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return typeBuilder.CreateType()!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly MethodInfo INVOKE_METHOD = typeof(IProxyInvocationHandler).GetMethod("Invoke");
|
private static readonly MethodInfo INVOKE_METHOD = typeof(IProxyInvocationHandler).GetMethod(nameof(IProxyInvocationHandler.Invoke))!;
|
||||||
private static readonly MethodInfo GET_METHODINFO_METHOD = typeof(MetaDataFactory).GetMethod("GetMethod", new Type[] { typeof(string), typeof(int) });
|
private static readonly MethodInfo GET_METHODINFO_METHOD = typeof(MetaDataFactory).GetMethod(nameof(MetaDataFactory.GetMethod))!;
|
||||||
|
|
||||||
private void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
|
private void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
|
||||||
{
|
{
|
||||||
MetaDataFactory.Add(interfaceType);
|
MetaDataFactory.Add(interfaceType);
|
||||||
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
|
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
|
||||||
PropertyInfo[] props = interfaceType.GetProperties();
|
// PropertyInfo[] props = interfaceType.GetProperties();
|
||||||
|
|
||||||
for (int i = 0; i < interfaceMethods.Length; i++)
|
for (int i = 0; i < interfaceMethods.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -272,7 +267,7 @@ namespace DynamicProxy
|
||||||
CallingConventions.Standard,
|
CallingConventions.Standard,
|
||||||
methodInfo.ReturnType, methodParameters);
|
methodInfo.ReturnType, methodParameters);
|
||||||
|
|
||||||
#region( "Handler Method IL Code" )
|
#region( "Handler Method IL Code" )
|
||||||
ILGenerator methodIL = methodBuilder.GetILGenerator();
|
ILGenerator methodIL = methodBuilder.GetILGenerator();
|
||||||
|
|
||||||
// load "this"
|
// load "this"
|
||||||
|
@ -283,7 +278,7 @@ namespace DynamicProxy
|
||||||
methodIL.Emit(OpCodes.Ldarg_0);
|
methodIL.Emit(OpCodes.Ldarg_0);
|
||||||
// load the name of the interface, used to get the MethodInfo object
|
// load the name of the interface, used to get the MethodInfo object
|
||||||
// from MetaDataFactory
|
// from MetaDataFactory
|
||||||
methodIL.Emit(OpCodes.Ldstr, interfaceType.FullName);
|
methodIL.Emit(OpCodes.Ldstr, interfaceType.FullName!);
|
||||||
// load the index, used to get the MethodInfo object
|
// load the index, used to get the MethodInfo object
|
||||||
// from MetaDataFactory
|
// from MetaDataFactory
|
||||||
methodIL.Emit(OpCodes.Ldc_I4, i);
|
methodIL.Emit(OpCodes.Ldc_I4, i);
|
||||||
|
@ -315,7 +310,7 @@ namespace DynamicProxy
|
||||||
|
|
||||||
if (methodInfo.ReturnType != typeof(void))
|
if (methodInfo.ReturnType != typeof(void))
|
||||||
{
|
{
|
||||||
// if the return type if a value type, then unbox the return value
|
// if the return type is a value type, then unbox the return value
|
||||||
// so that we don't get junk.
|
// so that we don't get junk.
|
||||||
if (methodInfo.ReturnType.IsValueType)
|
if (methodInfo.ReturnType.IsValueType)
|
||||||
{
|
{
|
||||||
|
@ -330,7 +325,7 @@ namespace DynamicProxy
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
methodIL.Emit((OpCode)OpCodeTypeMapper[methodInfo.ReturnType]);
|
methodIL.Emit(OpCodeTypeMapper[methodInfo.ReturnType]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,7 +338,7 @@ namespace DynamicProxy
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
methodIL.Emit(OpCodes.Ret);
|
methodIL.Emit(OpCodes.Ret);
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (int i = 0; i < props.Length; i++)
|
// for (int i = 0; i < props.Length; i++)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Xml;
|
||||||
using System.Xml;
|
|
||||||
|
|
||||||
namespace winsw.Extensions
|
namespace winsw.Extensions
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Xml;
|
||||||
using System.Xml;
|
|
||||||
|
|
||||||
namespace winsw.Extensions
|
namespace winsw.Extensions
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Xml;
|
||||||
using System.Xml;
|
|
||||||
using winsw.Util;
|
using winsw.Util;
|
||||||
|
|
||||||
namespace winsw.Extensions
|
namespace winsw.Extensions
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
|
@ -128,8 +127,8 @@ namespace winsw.Extensions
|
||||||
throw new ExtensionException(id, "Extension has been already loaded");
|
throw new ExtensionException(id, "Extension has been already loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
var extensionsConfig = ServiceDescriptor.ExtensionsConfiguration;
|
XmlNode? extensionsConfig = ServiceDescriptor.ExtensionsConfiguration;
|
||||||
XmlElement configNode = (extensionsConfig != null) ? extensionsConfig.SelectSingleNode("extension[@id='" + id + "'][1]") as XmlElement : null;
|
XmlElement? configNode = (extensionsConfig != null) ? extensionsConfig.SelectSingleNode("extension[@id='" + id + "'][1]") as XmlElement : null;
|
||||||
if (configNode == null)
|
if (configNode == null)
|
||||||
{
|
{
|
||||||
throw new ExtensionException(id, "Cannot get the configuration entry");
|
throw new ExtensionException(id, "Cannot get the configuration entry");
|
||||||
|
@ -165,13 +164,13 @@ namespace winsw.Extensions
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Type t = Type.GetType(className);
|
Type? t = Type.GetType(className);
|
||||||
if (t == null)
|
if (t == null)
|
||||||
{
|
{
|
||||||
throw new ExtensionException(id, "Class " + className + " does not exist");
|
throw new ExtensionException(id, "Class " + className + " does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
created = Activator.CreateInstance(t);
|
created = Activator.CreateInstance(t)!;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -403,7 +403,7 @@ namespace winsw
|
||||||
|
|
||||||
var buf = new byte[1024];
|
var buf = new byte[1024];
|
||||||
|
|
||||||
var baseDirectory = Path.GetDirectoryName(BaseLogFileName);
|
var baseDirectory = Path.GetDirectoryName(BaseLogFileName)!;
|
||||||
var baseFileName = Path.GetFileName(BaseLogFileName);
|
var baseFileName = Path.GetFileName(BaseLogFileName);
|
||||||
var logFile = BaseLogFileName + extension;
|
var logFile = BaseLogFileName + extension;
|
||||||
|
|
||||||
|
@ -411,10 +411,10 @@ namespace winsw
|
||||||
var sz = new FileInfo(logFile).Length;
|
var sz = new FileInfo(logFile).Length;
|
||||||
|
|
||||||
// We auto roll at time is configured then we need to create a timer and wait until time is elasped and roll the file over
|
// We auto roll at time is configured then we need to create a timer and wait until time is elasped and roll the file over
|
||||||
if (AutoRollAtTime != null)
|
if (AutoRollAtTime is TimeSpan autoRollAtTime)
|
||||||
{
|
{
|
||||||
// Run at start
|
// Run at start
|
||||||
var tickTime = SetupRollTimer();
|
var tickTime = SetupRollTimer(autoRollAtTime);
|
||||||
var timer = new System.Timers.Timer(tickTime);
|
var timer = new System.Timers.Timer(tickTime);
|
||||||
timer.Elapsed += (s, e) =>
|
timer.Elapsed += (s, e) =>
|
||||||
{
|
{
|
||||||
|
@ -444,7 +444,7 @@ namespace winsw
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// Recalculate the next interval
|
// Recalculate the next interval
|
||||||
timer.Interval = SetupRollTimer();
|
timer.Interval = SetupRollTimer(autoRollAtTime);
|
||||||
timer.Start();
|
timer.Start();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -543,7 +543,7 @@ namespace winsw
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
private void ZipOneFile(string sourceFilePath, string entryName, string zipFilePath)
|
private void ZipOneFile(string sourceFilePath, string entryName, string zipFilePath)
|
||||||
{
|
{
|
||||||
ZipArchive zipArchive = null;
|
ZipArchive? zipArchive = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
zipArchive = ZipFile.Open(zipFilePath, ZipArchiveMode.Update);
|
zipArchive = ZipFile.Open(zipFilePath, ZipArchiveMode.Update);
|
||||||
|
@ -565,7 +565,7 @@ namespace winsw
|
||||||
#else
|
#else
|
||||||
private void ZipOneFile(string sourceFilePath, string entryName, string zipFilePath)
|
private void ZipOneFile(string sourceFilePath, string entryName, string zipFilePath)
|
||||||
{
|
{
|
||||||
ZipFile zipFile = null;
|
ZipFile? zipFile = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
zipFile = new ZipFile(File.Open(zipFilePath, FileMode.OpenOrCreate));
|
zipFile = new ZipFile(File.Open(zipFilePath, FileMode.OpenOrCreate));
|
||||||
|
@ -590,11 +590,17 @@ namespace winsw
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private double SetupRollTimer()
|
private double SetupRollTimer(TimeSpan autoRollAtTime)
|
||||||
{
|
{
|
||||||
var nowTime = DateTime.Now;
|
var nowTime = DateTime.Now;
|
||||||
var scheduledTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day, AutoRollAtTime.Value.Hours,
|
var scheduledTime = new DateTime(
|
||||||
AutoRollAtTime.Value.Minutes, AutoRollAtTime.Value.Seconds, 0); // Specify your time HH,MM,SS
|
nowTime.Year,
|
||||||
|
nowTime.Month,
|
||||||
|
nowTime.Day,
|
||||||
|
autoRollAtTime.Hours,
|
||||||
|
autoRollAtTime.Minutes,
|
||||||
|
autoRollAtTime.Seconds,
|
||||||
|
0);
|
||||||
if (nowTime > scheduledTime)
|
if (nowTime > scheduledTime)
|
||||||
scheduledTime = scheduledTime.AddDays(1);
|
scheduledTime = scheduledTime.AddDays(1);
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,10 @@ namespace winsw.Logging
|
||||||
|
|
||||||
override protected void Append(LoggingEvent loggingEvent)
|
override protected void Append(LoggingEvent loggingEvent)
|
||||||
{
|
{
|
||||||
EventLog eventLog = provider.locate();
|
EventLog? eventLog = provider.locate();
|
||||||
if (eventLog != null)
|
|
||||||
{
|
// We write the event iff the provider is ready
|
||||||
// We write the event iff the provider is ready
|
eventLog?.WriteEntry(loggingEvent.RenderedMessage, toEventLogEntryType(loggingEvent.Level));
|
||||||
eventLog.WriteEntry(loggingEvent.RenderedMessage, toEventLogEntryType(loggingEvent.Level));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EventLogEntryType toEventLogEntryType(Level level)
|
private static EventLogEntryType toEventLogEntryType(Level level)
|
||||||
|
|
|
@ -133,7 +133,7 @@ namespace winsw.Native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetDomain(string s)
|
private static string? GetDomain(string s)
|
||||||
{
|
{
|
||||||
int stop = s.IndexOf("\\", StringComparison.Ordinal);
|
int stop = s.IndexOf("\\", StringComparison.Ordinal);
|
||||||
if (stop >= 0)
|
if (stop >= 0)
|
||||||
|
@ -151,7 +151,7 @@ namespace winsw.Native
|
||||||
private static string GetLocalAccountIfLocalAccount(string username)
|
private static string GetLocalAccountIfLocalAccount(string username)
|
||||||
{
|
{
|
||||||
var machinename = Environment.MachineName;
|
var machinename = Environment.MachineName;
|
||||||
string domain = GetDomain(username);
|
string? domain = GetDomain(username);
|
||||||
if (domain == null || domain.ToLower() == machinename.ToLower() || domain == ".")
|
if (domain == null || domain.ToLower() == machinename.ToLower() || domain == ".")
|
||||||
{
|
{
|
||||||
return GetLogin(username);
|
return GetLogin(username);
|
||||||
|
@ -287,7 +287,7 @@ namespace winsw.Native
|
||||||
internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_DELAYED_AUTO_START sfa);
|
internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, ref SERVICE_DELAYED_AUTO_START sfa);
|
||||||
|
|
||||||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
internal static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
|
internal static extern IntPtr OpenSCManager(string? machineName, string? databaseName, uint dwAccess);
|
||||||
|
|
||||||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
|
internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#if !NETCOREAPP
|
||||||
|
namespace System.Diagnostics.CodeAnalysis
|
||||||
|
{
|
||||||
|
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
|
||||||
|
internal sealed class AllowNullAttribute : Attribute { }
|
||||||
|
|
||||||
|
/// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
|
||||||
|
internal sealed class MaybeNullAttribute : Attribute { }
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,8 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using winsw.Configuration;
|
using winsw.Configuration;
|
||||||
using winsw.Native;
|
using winsw.Native;
|
||||||
|
@ -96,10 +96,10 @@ namespace winsw
|
||||||
|
|
||||||
private string SingleElement(string tagName)
|
private string SingleElement(string tagName)
|
||||||
{
|
{
|
||||||
return SingleElement(tagName, false);
|
return SingleElement(tagName, false)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string SingleElement(string tagName, bool optional)
|
private string? SingleElement(string tagName, bool optional)
|
||||||
{
|
{
|
||||||
var n = dom.SelectSingleNode("//" + tagName);
|
var n = dom.SelectSingleNode("//" + tagName);
|
||||||
if (n == null && !optional)
|
if (n == null && !optional)
|
||||||
|
@ -174,7 +174,7 @@ namespace winsw
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optionally specify a different Path to an executable to shutdown the service.
|
/// Optionally specify a different Path to an executable to shutdown the service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string StopExecutable => SingleElement("stopexecutable", true);
|
public string? StopExecutable => SingleElement("stopexecutable", true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Arguments or multiple optional argument elements which overrule the arguments element.
|
/// Arguments or multiple optional argument elements which overrule the arguments element.
|
||||||
|
@ -183,7 +183,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
string arguments = AppendTags("argument", null);
|
string? arguments = AppendTags("argument", null);
|
||||||
|
|
||||||
if (arguments == null)
|
if (arguments == null)
|
||||||
{
|
{
|
||||||
|
@ -206,19 +206,19 @@ namespace winsw
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiple optional startargument elements.
|
/// Multiple optional startargument elements.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Startarguments => AppendTags("startargument", Defaults.Startarguments);
|
public string? Startarguments => AppendTags("startargument", Defaults.Startarguments);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiple optional stopargument elements.
|
/// Multiple optional stopargument elements.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Stoparguments => AppendTags("stopargument", Defaults.Stoparguments);
|
public string? Stoparguments => AppendTags("stopargument", Defaults.Stoparguments);
|
||||||
|
|
||||||
public string WorkingDirectory
|
public string WorkingDirectory
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var wd = SingleElement("workingdirectory", true);
|
var wd = SingleElement("workingdirectory", true);
|
||||||
return string.IsNullOrEmpty(wd) ? Defaults.WorkingDirectory : wd;
|
return string.IsNullOrEmpty(wd) ? Defaults.WorkingDirectory : wd!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,65 +226,65 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
List<string> res = new List<string>();
|
XmlNode? argumentNode = ExtensionsConfiguration;
|
||||||
|
XmlNodeList? extensions = argumentNode?.SelectNodes("extension");
|
||||||
XmlNode argumentNode = ExtensionsConfiguration;
|
if (extensions == null)
|
||||||
XmlNodeList extensions = argumentNode?.SelectNodes("extension");
|
|
||||||
if (extensions != null)
|
|
||||||
{
|
{
|
||||||
foreach (XmlNode e in extensions)
|
return new List<string>(0);
|
||||||
{
|
|
||||||
XmlElement extension = (XmlElement)e;
|
|
||||||
string extensionId = XmlHelper.SingleAttribute<string>(extension, "id");
|
|
||||||
res.Add(extensionId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
List<string> result = new List<string>(extensions.Count);
|
||||||
|
for (int i = 0; i < extensions.Count; i++)
|
||||||
|
{
|
||||||
|
result.Add(XmlHelper.SingleAttribute<string>((XmlElement)extensions[i], "id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public XmlNode ExtensionsConfiguration => dom.SelectSingleNode("//extensions");
|
public XmlNode? ExtensionsConfiguration => dom.SelectSingleNode("//extensions");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Combines the contents of all the elements of the given name,
|
/// Combines the contents of all the elements of the given name,
|
||||||
/// or return null if no element exists. Handles whitespace quotation.
|
/// or return null if no element exists. Handles whitespace quotation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string AppendTags(string tagName, string defaultValue = null)
|
private string? AppendTags(string tagName, string? defaultValue = null)
|
||||||
{
|
{
|
||||||
XmlNode argumentNode = dom.SelectSingleNode("//" + tagName);
|
XmlNode? argumentNode = dom.SelectSingleNode("//" + tagName);
|
||||||
|
|
||||||
if (argumentNode == null)
|
if (argumentNode == null)
|
||||||
{
|
{
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
StringBuilder arguments = new StringBuilder();
|
||||||
|
|
||||||
|
XmlNodeList argumentNodeList = dom.SelectNodes("//" + tagName);
|
||||||
|
for (int i = 0; i < argumentNodeList.Count; i++)
|
||||||
{
|
{
|
||||||
string arguments = string.Empty;
|
arguments.Append(' ');
|
||||||
|
|
||||||
foreach (XmlElement argument in dom.SelectNodes("//" + tagName))
|
string token = Environment.ExpandEnvironmentVariables(argumentNodeList[i].InnerText);
|
||||||
|
|
||||||
|
if (token.StartsWith("\"") && token.EndsWith("\""))
|
||||||
{
|
{
|
||||||
string token = Environment.ExpandEnvironmentVariables(argument.InnerText);
|
// for backward compatibility, if the argument is already quoted, leave it as is.
|
||||||
|
// in earlier versions we didn't handle quotation, so the user might have worked
|
||||||
if (token.StartsWith("\"") && token.EndsWith("\""))
|
// around it by themselves
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (token.Contains(" "))
|
||||||
{
|
{
|
||||||
// for backward compatibility, if the argument is already quoted, leave it as is.
|
arguments.Append('"').Append(token).Append('"');
|
||||||
// in earlier versions we didn't handle quotation, so the user might have worked
|
continue;
|
||||||
// around it by themselves
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (token.Contains(" "))
|
|
||||||
{
|
|
||||||
token = '"' + token + '"';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
arguments += " " + token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return arguments;
|
arguments.Append(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return arguments.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -311,7 +311,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
string mode = null;
|
string? mode = null;
|
||||||
|
|
||||||
// first, backward compatibility with older configuration
|
// first, backward compatibility with older configuration
|
||||||
XmlElement e = (XmlElement)dom.SelectSingleNode("//logmode");
|
XmlElement e = (XmlElement)dom.SelectSingleNode("//logmode");
|
||||||
|
@ -469,19 +469,19 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var xmlNodeList = dom.SelectNodes("//depend");
|
XmlNodeList? nodeList = dom.SelectNodes("//depend");
|
||||||
if (xmlNodeList != null)
|
if (nodeList == null)
|
||||||
{
|
{
|
||||||
ArrayList serviceDependencies = new ArrayList();
|
return Defaults.ServiceDependencies;
|
||||||
foreach (XmlNode depend in xmlNodeList)
|
|
||||||
{
|
|
||||||
serviceDependencies.Add(depend.InnerText);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (string[])serviceDependencies.ToArray(typeof(string));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Defaults.ServiceDependencies;
|
string[] serviceDependencies = new string[nodeList.Count];
|
||||||
|
for (int i = 0; i < nodeList.Count; i++)
|
||||||
|
{
|
||||||
|
serviceDependencies[i] = nodeList[i].InnerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serviceDependencies;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,10 +558,12 @@ namespace winsw
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
Dictionary<string, string> map = new Dictionary<string, string>();
|
Dictionary<string, string> map = new Dictionary<string, string>();
|
||||||
foreach (XmlNode n in dom.SelectNodes("//env"))
|
XmlNodeList nodeList = dom.SelectNodes("//env");
|
||||||
|
for (int i = 0; i < nodeList.Count; i++)
|
||||||
{
|
{
|
||||||
string key = n.Attributes["name"].Value;
|
XmlNode node = nodeList[i];
|
||||||
string value = Environment.ExpandEnvironmentVariables(n.Attributes["value"].Value);
|
string key = node.Attributes["name"].Value;
|
||||||
|
string value = Environment.ExpandEnvironmentVariables(node.Attributes["value"].Value);
|
||||||
map[key] = value;
|
map[key] = value;
|
||||||
|
|
||||||
Environment.SetEnvironmentVariable(key, value);
|
Environment.SetEnvironmentVariable(key, value);
|
||||||
|
@ -579,22 +581,22 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var xmlNodeList = dom.SelectNodes("//download");
|
XmlNodeList? nodeList = dom.SelectNodes("//download");
|
||||||
if (xmlNodeList == null)
|
if (nodeList == null)
|
||||||
{
|
{
|
||||||
return Defaults.Downloads;
|
return Defaults.Downloads;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Download> r = new List<Download>();
|
List<Download> result = new List<Download>(nodeList.Count);
|
||||||
foreach (XmlNode n in xmlNodeList)
|
for (int i = 0; i < nodeList.Count; i++)
|
||||||
{
|
{
|
||||||
if (n is XmlElement el)
|
if (nodeList[i] is XmlElement element)
|
||||||
{
|
{
|
||||||
r.Add(new Download(el));
|
result.Add(new Download(element));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,41 +604,35 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
List<SC_ACTION> r = new List<SC_ACTION>();
|
XmlNodeList? childNodes = dom.SelectNodes("//onfailure");
|
||||||
var childNodes = dom.SelectNodes("//onfailure");
|
if (childNodes == null)
|
||||||
if (childNodes != null)
|
|
||||||
{
|
{
|
||||||
foreach (XmlNode n in childNodes)
|
return new List<SC_ACTION>(0);
|
||||||
{
|
|
||||||
SC_ACTION_TYPE type;
|
|
||||||
string action = n.Attributes["action"].Value;
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case "restart":
|
|
||||||
type = SC_ACTION_TYPE.SC_ACTION_RESTART;
|
|
||||||
break;
|
|
||||||
case "none":
|
|
||||||
type = SC_ACTION_TYPE.SC_ACTION_NONE;
|
|
||||||
break;
|
|
||||||
case "reboot":
|
|
||||||
type = SC_ACTION_TYPE.SC_ACTION_REBOOT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Exception("Invalid failure action: " + action);
|
|
||||||
}
|
|
||||||
|
|
||||||
XmlAttribute delay = n.Attributes["delay"];
|
|
||||||
r.Add(new SC_ACTION(type, delay != null ? ParseTimeSpan(delay.Value) : TimeSpan.Zero));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
List<SC_ACTION> result = new List<SC_ACTION>(childNodes.Count);
|
||||||
|
for (int i = 0; i < childNodes.Count; i++)
|
||||||
|
{
|
||||||
|
XmlNode node = childNodes[i];
|
||||||
|
string action = node.Attributes["action"].Value;
|
||||||
|
SC_ACTION_TYPE type = action switch
|
||||||
|
{
|
||||||
|
"restart" => SC_ACTION_TYPE.SC_ACTION_RESTART,
|
||||||
|
"none" => SC_ACTION_TYPE.SC_ACTION_NONE,
|
||||||
|
"reboot" => SC_ACTION_TYPE.SC_ACTION_REBOOT,
|
||||||
|
_ => throw new Exception("Invalid failure action: " + action)
|
||||||
|
};
|
||||||
|
XmlAttribute? delay = node.Attributes["delay"];
|
||||||
|
result.Add(new SC_ACTION(type, delay != null ? ParseTimeSpan(delay.Value) : TimeSpan.Zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan ResetFailureAfter => SingleTimeSpanElement(dom, "resetfailure", Defaults.ResetFailureAfter);
|
public TimeSpan ResetFailureAfter => SingleTimeSpanElement(dom, "resetfailure", Defaults.ResetFailureAfter);
|
||||||
|
|
||||||
protected string GetServiceAccountPart(string subNodeName)
|
protected string? GetServiceAccountPart(string subNodeName)
|
||||||
{
|
{
|
||||||
var node = dom.SelectSingleNode("//serviceaccount");
|
var node = dom.SelectSingleNode("//serviceaccount");
|
||||||
|
|
||||||
|
@ -652,15 +648,15 @@ namespace winsw
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string AllowServiceLogon => GetServiceAccountPart("allowservicelogon");
|
protected string? AllowServiceLogon => GetServiceAccountPart("allowservicelogon");
|
||||||
|
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
protected string serviceAccountDomain => GetServiceAccountPart("domain");
|
protected string? serviceAccountDomain => GetServiceAccountPart("domain");
|
||||||
|
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
protected string serviceAccountName => GetServiceAccountPart("user");
|
protected string? serviceAccountName => GetServiceAccountPart("user");
|
||||||
|
|
||||||
public string ServiceAccountPassword => GetServiceAccountPart("password");
|
public string? ServiceAccountPassword => GetServiceAccountPart("password");
|
||||||
|
|
||||||
public string ServiceAccountUser => (serviceAccountDomain ?? "NULL") + @"\" + (serviceAccountName ?? "NULL");
|
public string ServiceAccountUser => (serviceAccountDomain ?? "NULL") + @"\" + (serviceAccountName ?? "NULL");
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,17 @@ namespace winsw.Util
|
||||||
/// <param name="callback">Completion callback. If null, the completion won't be monitored</param>
|
/// <param name="callback">Completion callback. If null, the completion won't be monitored</param>
|
||||||
/// <param name="logHandler">Log handler. If enabled, logs will be redirected to the process and then reported</param>
|
/// <param name="logHandler">Log handler. If enabled, logs will be redirected to the process and then reported</param>
|
||||||
/// <param name="redirectStdin">Redirect standard input</param>
|
/// <param name="redirectStdin">Redirect standard input</param>
|
||||||
public static void StartProcessAndCallbackForExit(Process processToStart, string executable = null, string arguments = null, Dictionary<string, string> envVars = null,
|
public static void StartProcessAndCallbackForExit(
|
||||||
string workingDirectory = null, ProcessPriorityClass? priority = null, ProcessCompletionCallback callback = null, bool redirectStdin = true, LogHandler logHandler = null, bool hideWindow = false)
|
Process processToStart,
|
||||||
|
string? executable = null,
|
||||||
|
string? arguments = null,
|
||||||
|
Dictionary<string, string>? envVars = null,
|
||||||
|
string? workingDirectory = null,
|
||||||
|
ProcessPriorityClass? priority = null,
|
||||||
|
ProcessCompletionCallback? callback = null,
|
||||||
|
bool redirectStdin = true,
|
||||||
|
LogHandler? logHandler = null,
|
||||||
|
bool hideWindow = false)
|
||||||
{
|
{
|
||||||
var ps = processToStart.StartInfo;
|
var ps = processToStart.StartInfo;
|
||||||
ps.FileName = executable ?? ps.FileName;
|
ps.FileName = executable ?? ps.FileName;
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace winsw.Util
|
||||||
private static extern bool FreeConsole();
|
private static extern bool FreeConsole();
|
||||||
|
|
||||||
[DllImport(KERNEL32)]
|
[DllImport(KERNEL32)]
|
||||||
private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);
|
private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate? HandlerRoutine, bool Add);
|
||||||
|
|
||||||
// Delegate type to be used as the Handler Routine for SCCH
|
// Delegate type to be used as the Handler Routine for SCCH
|
||||||
private delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType);
|
private delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
|
||||||
|
@ -11,10 +12,10 @@ namespace winsw.Util
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">Parent node</param>
|
/// <param name="node">Parent node</param>
|
||||||
/// <param name="tagName">Element name</param>
|
/// <param name="tagName">Element name</param>
|
||||||
/// <param name="optional">If optional, don't throw an exception if the elemen is missing</param>
|
/// <param name="optional">If optional, don't throw an exception if the element is missing</param>
|
||||||
/// <returns>String value or null</returns>
|
/// <returns>String value or null</returns>
|
||||||
/// <exception cref="InvalidDataException">The required element is missing</exception>
|
/// <exception cref="InvalidDataException">The required element is missing</exception>
|
||||||
public static string SingleElement(XmlNode node, string tagName, bool optional)
|
public static string? SingleElement(XmlNode node, string tagName, bool optional)
|
||||||
{
|
{
|
||||||
var n = node.SelectSingleNode(tagName);
|
var n = node.SelectSingleNode(tagName);
|
||||||
if (n == null && !optional)
|
if (n == null && !optional)
|
||||||
|
@ -28,10 +29,10 @@ namespace winsw.Util
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">Parent node</param>
|
/// <param name="node">Parent node</param>
|
||||||
/// <param name="tagName">Element name</param>
|
/// <param name="tagName">Element name</param>
|
||||||
/// <param name="optional">If otional, don't throw an exception if the elemen is missing</param>
|
/// <param name="optional">If otional, don't throw an exception if the element is missing</param>
|
||||||
/// <returns>String value or null</returns>
|
/// <returns>String value or null</returns>
|
||||||
/// <exception cref="InvalidDataException">The required element is missing</exception>
|
/// <exception cref="InvalidDataException">The required element is missing</exception>
|
||||||
public static XmlNode SingleNode(XmlNode node, string tagName, bool optional)
|
public static XmlNode? SingleNode(XmlNode node, string tagName, bool optional)
|
||||||
{
|
{
|
||||||
var n = node.SelectSingleNode(tagName);
|
var n = node.SelectSingleNode(tagName);
|
||||||
if (n == null && !optional)
|
if (n == null && !optional)
|
||||||
|
@ -54,7 +55,7 @@ namespace winsw.Util
|
||||||
throw new InvalidDataException("Attribute <" + attributeName + "> is missing in configuration XML");
|
throw new InvalidDataException("Attribute <" + attributeName + "> is missing in configuration XML");
|
||||||
}
|
}
|
||||||
|
|
||||||
return SingleAttribute(node, attributeName, default(TAttributeType));
|
return SingleAttribute<TAttributeType>(node, attributeName, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -64,7 +65,8 @@ namespace winsw.Util
|
||||||
/// <param name="attributeName">Attribute name</param>
|
/// <param name="attributeName">Attribute name</param>
|
||||||
/// <param name="defaultValue">Default value</param>
|
/// <param name="defaultValue">Default value</param>
|
||||||
/// <returns>Attribute value (or default)</returns>
|
/// <returns>Attribute value (or default)</returns>
|
||||||
public static TAttributeType SingleAttribute<TAttributeType>(XmlElement node, string attributeName, TAttributeType defaultValue)
|
[return: MaybeNull]
|
||||||
|
public static TAttributeType SingleAttribute<TAttributeType>(XmlElement node, string attributeName, [AllowNull] TAttributeType defaultValue)
|
||||||
{
|
{
|
||||||
if (!node.HasAttribute(attributeName))
|
if (!node.HasAttribute(attributeName))
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net20;net40;net461;netcoreapp3.1</TargetFrameworks>
|
<TargetFrameworks>net20;net40;net461;netcoreapp3.1</TargetFrameworks>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
<Version><!-- Populated by AppVeyor --></Version>
|
<Version><!-- Populated by AppVeyor --></Version>
|
||||||
<RootNamespace>winsw</RootNamespace>
|
<RootNamespace>winsw</RootNamespace>
|
||||||
<SignAssembly>true</SignAssembly>
|
<SignAssembly>true</SignAssembly>
|
||||||
|
|
|
@ -89,17 +89,19 @@ namespace WMI
|
||||||
|
|
||||||
public WmiRoot() : this(null) { }
|
public WmiRoot() : this(null) { }
|
||||||
|
|
||||||
public WmiRoot(string machineName)
|
public WmiRoot(string? machineName)
|
||||||
{
|
{
|
||||||
ConnectionOptions options = new ConnectionOptions();
|
ConnectionOptions options = new ConnectionOptions
|
||||||
options.EnablePrivileges = true;
|
{
|
||||||
options.Impersonation = ImpersonationLevel.Impersonate;
|
EnablePrivileges = true,
|
||||||
options.Authentication = AuthenticationLevel.PacketPrivacy;
|
Impersonation = ImpersonationLevel.Impersonate,
|
||||||
|
Authentication = AuthenticationLevel.PacketPrivacy,
|
||||||
|
};
|
||||||
|
|
||||||
string path;
|
string path;
|
||||||
|
|
||||||
if (machineName != null)
|
if (machineName != null)
|
||||||
path = string.Format(@"\\{0}\root\cimv2", machineName);
|
path = $@"\\{machineName}\root\cimv2";
|
||||||
else
|
else
|
||||||
path = @"\root\cimv2";
|
path = @"\root\cimv2";
|
||||||
scope = new ManagementScope(path, options);
|
scope = new ManagementScope(path, options);
|
||||||
|
@ -113,7 +115,7 @@ namespace WMI
|
||||||
|
|
||||||
abstract class BaseHandler : IProxyInvocationHandler
|
abstract class BaseHandler : IProxyInvocationHandler
|
||||||
{
|
{
|
||||||
public abstract object Invoke(object proxy, MethodInfo method, object[] args);
|
public abstract object? Invoke(object proxy, MethodInfo method, object[] args);
|
||||||
|
|
||||||
protected void CheckError(ManagementBaseObject result)
|
protected void CheckError(ManagementBaseObject result)
|
||||||
{
|
{
|
||||||
|
@ -127,9 +129,9 @@ namespace WMI
|
||||||
{
|
{
|
||||||
private readonly ManagementObject _mo;
|
private readonly ManagementObject _mo;
|
||||||
|
|
||||||
public InstanceHandler(ManagementObject o) { _mo = o; }
|
public InstanceHandler(ManagementObject o) => _mo = o;
|
||||||
|
|
||||||
public override object Invoke(object proxy, MethodInfo method, object[] args)
|
public override object? Invoke(object proxy, MethodInfo method, object[] args)
|
||||||
{
|
{
|
||||||
if (method.DeclaringType == typeof(IWmiObject))
|
if (method.DeclaringType == typeof(IWmiObject))
|
||||||
{
|
{
|
||||||
|
@ -153,7 +155,7 @@ namespace WMI
|
||||||
|
|
||||||
ManagementBaseObject wmiArgs = _mo.GetMethodParameters(method.Name);
|
ManagementBaseObject wmiArgs = _mo.GetMethodParameters(method.Name);
|
||||||
for (int i = 0; i < args.Length; i++)
|
for (int i = 0; i < args.Length; i++)
|
||||||
wmiArgs[Capitalize(methodArgs[i].Name)] = args[i];
|
wmiArgs[Capitalize(methodArgs[i].Name!)] = args[i];
|
||||||
|
|
||||||
CheckError(_mo.InvokeMethod(method.Name, wmiArgs, null));
|
CheckError(_mo.InvokeMethod(method.Name, wmiArgs, null));
|
||||||
return null;
|
return null;
|
||||||
|
@ -172,7 +174,7 @@ namespace WMI
|
||||||
|
|
||||||
public ClassHandler(ManagementClass mc, string wmiClass) { _mc = mc; _wmiClass = wmiClass; }
|
public ClassHandler(ManagementClass mc, string wmiClass) { _mc = mc; _wmiClass = wmiClass; }
|
||||||
|
|
||||||
public override object Invoke(object proxy, MethodInfo method, object[] args)
|
public override object? Invoke(object proxy, MethodInfo method, object[] args)
|
||||||
{
|
{
|
||||||
ParameterInfo[] methodArgs = method.GetParameters();
|
ParameterInfo[] methodArgs = method.GetParameters();
|
||||||
|
|
||||||
|
@ -185,7 +187,7 @@ namespace WMI
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
query += " AND ";
|
query += " AND ";
|
||||||
|
|
||||||
query += ' ' + Capitalize(methodArgs[i].Name) + " = '" + args[i] + "'";
|
query += ' ' + Capitalize(methodArgs[i].Name!) + " = '" + args[i] + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
ManagementObjectSearcher searcher = new ManagementObjectSearcher(_mc.Scope, new ObjectQuery(query));
|
ManagementObjectSearcher searcher = new ManagementObjectSearcher(_mc.Scope, new ObjectQuery(query));
|
||||||
|
@ -198,7 +200,7 @@ namespace WMI
|
||||||
|
|
||||||
ManagementBaseObject wmiArgs = _mc.GetMethodParameters(method.Name);
|
ManagementBaseObject wmiArgs = _mc.GetMethodParameters(method.Name);
|
||||||
for (int i = 0; i < args.Length; i++)
|
for (int i = 0; i < args.Length; i++)
|
||||||
wmiArgs[Capitalize(methodArgs[i].Name)] = args[i];
|
wmiArgs[Capitalize(methodArgs[i].Name!)] = args[i];
|
||||||
|
|
||||||
CheckError(_mc.InvokeMethod(method.Name, wmiArgs, null));
|
CheckError(_mc.InvokeMethod(method.Name, wmiArgs, null));
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in New Issue