refactoring

pull/1/head
a.bozhenov 5 years ago
parent 077ecabbaa
commit 24e9d763ee

@ -60,7 +60,7 @@ namespace TestApp
Log.Info($"Client '{obj.Endpoint.Address}:{obj.Endpoint.Port}' disconnected"); Log.Info($"Client '{obj.Endpoint.Address}:{obj.Endpoint.Port}' disconnected");
} }
private void Host_OnConnect(ExClient obj) private void Host_OnConnect(IClient obj)
{ {
Log.Info($"Client '{obj.Socket.Endpoint.Address}:{obj.Socket.Endpoint.Port}' connected"); Log.Info($"Client '{obj.Socket.Endpoint.Address}:{obj.Socket.Endpoint.Port}' connected");
} }

@ -12,7 +12,7 @@ namespace Consumer
protected override void StartAction() protected override void StartAction()
{ {
ReadServiceInfo(); ReadServiceInfo();
AutoregisterInboxes(UseHost()); AutoregisterInboxes(UseHost(8802));
Sheduller.RemindEvery(TimeSpan.FromSeconds(1), () => Sheduller.RemindEvery(TimeSpan.FromSeconds(1), () =>
{ {

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Net;
using System.Threading; using System.Threading;
using ZeroLevel; using ZeroLevel;
using ZeroLevel.Network; using ZeroLevel.Network;
@ -19,7 +20,9 @@ namespace Processor
_processThread.Start(); _processThread.Start();
ReadServiceInfo(); ReadServiceInfo();
AutoregisterInboxes(UseHost()); AutoregisterInboxes(UseHost(8801));
Exchange.RoutesStorage.Set("test.consumer", new IPEndPoint(IPAddress.Loopback, 8802));
Sheduller.RemindEvery(TimeSpan.FromSeconds(1), () => Sheduller.RemindEvery(TimeSpan.FromSeconds(1), () =>
{ {
@ -32,9 +35,12 @@ namespace Processor
{ {
while (_incoming.IsCompleted == false) while (_incoming.IsCompleted == false)
{ {
int data = _incoming.Take(); long data;
var next = (int)(data ^ Interlocked.Increment(ref _proceed)); if (_incoming.TryTake(out data, 100))
Exchange.Request<int, bool>("test.consumer", "handle", next, result => { }); {
var next = (int)(data ^ Interlocked.Increment(ref _proceed));
Exchange.Request<int, bool>("test.consumer", "handle", next, result => { });
}
} }
} }
@ -62,12 +68,12 @@ namespace Processor
return true; return true;
} }
BlockingCollection<int> _incoming = new BlockingCollection<int>(); BlockingCollection<long> _incoming = new BlockingCollection<long>();
[ExchangeHandler("handle")] [ExchangeReplier("handle")]
public void Handler(ISocketClient client, int data) public bool Handler(ISocketClient client, long data)
{ {
_incoming.Add(data); return _incoming.TryAdd(data);
} }
} }
} }

@ -1,4 +1,5 @@
using System; using System;
using System.Net;
using System.Threading; using System.Threading;
using ZeroLevel; using ZeroLevel;
using ZeroLevel.Network; using ZeroLevel.Network;
@ -14,13 +15,51 @@ namespace Source
ReadServiceInfo(); ReadServiceInfo();
AutoregisterInboxes(UseHost()); AutoregisterInboxes(UseHost());
Sheduller.RemindEvery(TimeSpan.FromMilliseconds(100), () => Exchange.RoutesStorage.Set("test.processor", new IPEndPoint(IPAddress.Loopback, 8801));
/*Sheduller.RemindEvery(TimeSpan.FromMilliseconds(100), () =>
{ {
if (Exchange.Send("test.processor", "handle", Environment.TickCount)) if (Exchange.Send("test.processor", "handle", Environment.TickCount))
{ {
Interlocked.Increment(ref _proceed); Interlocked.Increment(ref _proceed);
} }
}); });*/
try
{
using (var waiter = new ManualResetEventSlim(false))
{
while (true)
{
try
{
var ir = Exchange.GetConnection("test.processor")?.Request<long, bool>("handle"
, Environment.TickCount
, s =>
{
Interlocked.Increment(ref _proceed);
waiter.Set();
});
if (ir == null || ir.Success == false)
{
Thread.Sleep(300);
waiter.Set();
}
}
catch
{
Thread.Sleep(300);
waiter.Set();
}
waiter.Wait(5000);
waiter.Reset();
}
}
}
catch
{
Thread.Sleep(300);
}
} }
protected override void StopAction() protected override void StopAction()

@ -13,71 +13,26 @@ namespace Watcher
protected override void StartAction() protected override void StartAction()
{ {
ReadServiceInfo(); ReadServiceInfo();
AutoregisterInboxes(UseHost());
Sheduller.RemindEvery(TimeSpan.FromMilliseconds(350), () => Sheduller.RemindEvery(TimeSpan.FromMilliseconds(350), () =>
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine("Discovery table");
sb.AppendLine("—————————————————————————————————————————————————————————————————————————"); sb.AppendLine("—————————————————————————————————————————————————————————————————————————");
var success = Exchange.RequestBroadcastByGroup<ZeroServiceInfo>("Test", "meta", records => foreach (var record in Exchange.DiscoveryStorage.GetAll())
{ {
if (records.Any() == false) sb.AppendLine($"\t{record.Key}:\t{record.Value.Address}:{record.Value.Port}");
{
Log.Info("No services");
}
foreach (var record in records.OrderBy(r=>r.Name))
{
sb.Append(record.Name);
sb.Append(" (");
sb.Append(record.Version);
sb.AppendLine(")");
sb.AppendLine(record.ServiceKey);
sb.AppendLine(record.ServiceType);
sb.AppendLine(record.ServiceGroup);
sb.AppendLine();
}
});
if (!success)
{
Log.Warning("[WatcherService] Can't send broadcast reqeust for meta");
} }
success = Exchange.RequestBroadcastByType<long>("Sources", "Proceed", records => sb.AppendLine("Routing table");
{ sb.AppendLine("—————————————————————————————————————————————————————————————————————————");
sb.AppendLine("-----------------------------------------------------------------------------");
sb.Append("Source send items: ");
sb.AppendLine(records.Sum().ToString());
});
if (!success)
{
Log.Warning("[WatcherService] Can't send broadcast reqeust to 'Sources'");
}
success = Exchange.RequestBroadcastByType<long>("Core", "Proceed", records => foreach (var record in Exchange.RoutesStorage.GetAll())
{
sb.AppendLine("-----------------------------------------------------------------------------");
sb.Append("Proccessor handle and send items: ");
sb.AppendLine(records.Sum().ToString());
});
if (!success)
{ {
Log.Warning("[WatcherService] Can't send broadcast reqeust to 'Core'"); sb.AppendLine($"\t{record.Key}:\t{record.Value.Address}:{record.Value.Port}");
} }
success = Exchange.RequestBroadcastByType<long>("Destination", "Proceed", records =>
{
sb.AppendLine("-----------------------------------------------------------------------------");
sb.Append("Consumer catch: ");
sb.AppendLine(records.Sum().ToString());
});
if (!success)
{
Log.Warning("[WatcherService] Can't send broadcast reqeust to 'Destination'");
}
sb.AppendLine("—————————————————————————————————————————————————————————————————————————");
sb.AppendLine(); sb.AppendLine();
Console.Clear(); Console.Clear();
Console.WriteLine($"Watch info: \r\n{sb}"); Console.WriteLine($"Watch info: \r\n{sb}");
@ -87,17 +42,5 @@ namespace Watcher
protected override void StopAction() protected override void StopAction()
{ {
} }
[ExchangeReplierWithoutArg("meta")]
public ZeroServiceInfo GetCounter(ISocketClient client)
{
return ServiceInfo;
}
[ExchangeReplierWithoutArg("ping")]
public bool Ping(ISocketClient client)
{
return true;
}
} }
} }

@ -6,8 +6,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Data.Common" Version="4.3.0" /> <PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.6.1" /> <PackageReference Include="System.Data.SqlClient" Version="4.7.0" />
<PackageReference Include="System.Security.Permissions" Version="4.5.0" /> <PackageReference Include="System.Security.Permissions" Version="4.6.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -7,9 +7,12 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="xunit" Version="2.4.0" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -1,7 +0,0 @@
namespace ZeroLevel.Services.AsService.Builder
{
public interface EnvironmentBuilder
{
HostEnvironment Build();
}
}

@ -1,15 +0,0 @@
using System;
namespace ZeroLevel.Services.AsService.Builder
{
public interface HostBuilder
{
HostEnvironment Environment { get; }
HostSettings Settings { get; }
Host Build(ServiceBuilder serviceBuilder);
void Match<T>(Action<T> callback)
where T : class, HostBuilder;
}
}

@ -1,7 +0,0 @@
namespace ZeroLevel.Services.AsService.Builder
{
public interface ServiceBuilder
{
ServiceHandle Build(HostSettings settings);
}
}

@ -1,16 +0,0 @@
namespace ZeroLevel.Services.AsService
{
public class Credentials
{
public Credentials(string username, string password, ServiceAccount account)
{
Username = username;
Account = account;
Password = password;
}
public string Username { get; }
public string Password { get; }
public ServiceAccount Account { get; }
}
}

@ -1,25 +0,0 @@
namespace ZeroLevel.Services.AsService
{
public enum ExitCode
{
Ok = 0,
ServiceAlreadyInstalled = 1242,
ServiceNotInstalled = 1243,
ServiceAlreadyRunning = 1056,
ServiceNotRunning = 1062,
ServiceControlRequestFailed = 1064,
AbnormalExit = 1067,
SudoRequired = 2,
NotRunningOnWindows = 11
}
/// <summary>
/// A Host can be a number of configured service hosts, from installers to service runners
/// </summary>
public interface Host
{
/// <summary>
/// Runs the configured host
/// </summary>
ExitCode Run();
}
}

@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace ZeroLevel.Services.AsService
{
public interface Configurator
{
IEnumerable<ValidateResult> Validate();
}
}

@ -1,15 +0,0 @@
using ZeroLevel.Services.AsService.Builder;
namespace ZeroLevel.Services.AsService
{
public interface HostBuilderConfigurator :
Configurator
{
/// <summary>
/// Configures the host builder.
/// </summary>
/// <param name="builder">The host builder.</param>
/// <returns>The configured host builder.</returns>
HostBuilder Configure(HostBuilder builder);
}
}

@ -1,128 +0,0 @@
using System;
namespace ZeroLevel.Services.AsService
{
public interface HostConfigurator
{
/// <summary>
/// Specifies the name of the service as it should be displayed in the service control manager
/// </summary>
/// <param name="name"> </param>
void SetDisplayName(string name);
/// <summary>
/// Specifies the name of the service as it is registered in the service control manager
/// </summary>
/// <param name="name"> </param>
void SetServiceName(string name);
/// <summary>
/// Specifies the description of the service that is displayed in the service control manager
/// </summary>
/// <param name="description"> </param>
void SetDescription(string description);
/// <summary>
/// Specifies the service instance name that should be used when the service is registered
/// </summary>
/// <param name="instanceName"> </param>
void SetInstanceName(string instanceName);
/// <summary>
/// Sets the amount of time to wait for the service to start before timing out. Default is 10 seconds.
/// </summary>
/// <param name="startTimeOut"></param>
void SetStartTimeout(TimeSpan startTimeOut);
/// <summary>
/// Sets the amount of time to wait for the service to stop before timing out. Default is 10 seconds.
/// </summary>
/// <param name="stopTimeOut"></param>
void SetStopTimeout(TimeSpan stopTimeOut);
/// <summary>
/// Enable pause and continue support for the service (default is disabled)
/// </summary>
void EnablePauseAndContinue();
/// <summary>
/// Enable support for service shutdown (signaled by the host OS)
/// </summary>
void EnableShutdown();
/// <summary>
/// Enables support for the session changed event
/// </summary>
void EnableSessionChanged();
/// <summary>
/// Enables support for power events (signaled by the host OS)
/// </summary>
void EnablePowerEvents();
/// <summary>
/// Specifies the builder factory to use when the service is invoked
/// </summary>
/// <param name="hostBuilderFactory"> </param>
void UseHostBuilder(HostBuilderFactory hostBuilderFactory);
/// <summary>
/// Sets the service builder to use for creating the service
/// </summary>
/// <param name="serviceBuilderFactory"> </param>
void UseServiceBuilder(ServiceBuilderFactory serviceBuilderFactory);
/// <summary>
/// Sets the environment builder to use for creating the service (defaults to Windows)
/// </summary>
/// <param name="environmentBuilderFactory"> </param>
void UseEnvironmentBuilder(EnvironmentBuilderFactory environmentBuilderFactory);
/// <summary>
/// Adds a a configurator for the host builder to the configurator
/// </summary>
/// <param name="configurator"> </param>
void AddConfigurator(HostBuilderConfigurator configurator);
/// <summary>
/// Parses the command line options and applies them to the host configurator
/// </summary>
void ApplyCommandLine();
/// <summary>
/// Parses the command line options from the specified command line and applies them to the host configurator
/// </summary>
/// <param name="commandLine"></param>
void ApplyCommandLine(string commandLine);
/// <summary>
/// Adds a command line switch (--name) that can be either true or false. Switches are CASE SeNsITiVe
/// </summary>
/// <param name="name">The name of the switch, as it will appear on the command line</param>
/// <param name="callback"></param>
void AddCommandLineSwitch(string name, Action<bool> callback);
/// <summary>
/// Adds a command line definition (-name:value) that can be specified. the name is case sensitive. If the
/// definition
/// </summary>
/// <param name="name"></param>
/// <param name="callback"></param>
void AddCommandLineDefinition(string name, Action<string> callback);
/// <summary>
/// Specifies a callback to be run when Topshelf encounters an exception while starting, running
/// or stopping. This callback does not replace Topshelf's default handling of any exceptions, and
/// is intended to allow for local cleanup, logging, etc. This is not required, and is only invoked
/// if a callback is provided.
/// </summary>
/// <param name="callback">The action to run when an exception occurs.</param>
void OnException(Action<Exception> callback);
/// <summary>
/// The policy that will be used when Topself detects an UnhandledException in the
/// application. The default policy is to log an error and to stop the service.
/// </summary>
UnhandledExceptionPolicyCode UnhandledExceptionPolicy { get; set; }
}
}

@ -1,36 +0,0 @@
using System;
namespace ZeroLevel.Services.AsService
{
[Serializable]
public enum ValidationResultDisposition
{
Success,
Warning,
Failure,
}
public interface ValidateResult
{
/// <summary>
/// The disposition of the result, any Failure items will prevent
/// the configuration from completing.
/// </summary>
ValidationResultDisposition Disposition { get; }
/// <summary>
/// The message associated with the result
/// </summary>
string Message { get; }
/// <summary>
/// The key associated with the result (chained if configurators are nested)
/// </summary>
string Key { get; }
/// <summary>
/// The value associated with the result
/// </summary>
string Value { get; }
}
}

@ -1,26 +0,0 @@
using System;
namespace ZeroLevel.Services.AsService
{
/// <summary>
/// Allows the service to control the host while running
/// </summary>
public interface HostControl
{
/// <summary>
/// Tells the Host that the service is still starting, which resets the
/// timeout.
/// </summary>
void RequestAdditionalTime(TimeSpan timeRemaining);
/// <summary>
/// Stops the Host
/// </summary>
void Stop();
/// <summary>
/// Stops the Host, returning the specified exit code
/// </summary>
void Stop(ExitCode exitCode);
}
}

@ -1,90 +0,0 @@
using System;
namespace ZeroLevel.Services.AsService
{
/// <summary>
/// Abstracts the environment in which the host in running (different OS versions, platforms,
/// bitness, etc.)
/// </summary>
public interface HostEnvironment
{
string CommandLine { get; }
/// <summary>
/// Determines if the service is running as an administrator
/// </summary>
bool IsAdministrator { get; }
/// <summary>
/// Determines if the process is running as a service
/// </summary>
bool IsRunningAsAService { get; }
/// <summary>
/// Determines if the service is installed
/// </summary>
/// <param name="serviceName">The name of the service as it is registered</param>
/// <returns>True if the service is installed, otherwise false</returns>
bool IsServiceInstalled(string serviceName);
/// <summary>
/// Determines if the service is stopped, to prevent a debug instance from being started
/// </summary>
/// <param name="serviceName"></param>
/// <returns></returns>
bool IsServiceStopped(string serviceName);
/// <summary>
/// Start the service using operating system controls
/// </summary>
/// <param name="serviceName">The name of the service</param>
/// <param name="startTimeOut">Waits for the service to reach the running status in the specified time.</param>
void StartService(string serviceName, TimeSpan startTimeOut);
/// <summary>
/// Stop the service using operating system controls
/// </summary>
/// <param name="serviceName">The name of the service</param>
/// <param name="stopTimeOut">Waits for the service to reach the stopeed status in the specified time.</param>
void StopService(string serviceName, TimeSpan stopTimeOut);
/// <summary>
/// Install the service using the settings provided
/// </summary>
/// <param name="settings"></param>
/// <param name="beforeInstall"> </param>
/// <param name="afterInstall"> </param>
/// <param name="beforeRollback"> </param>
/// <param name="afterRollback"> </param>
void InstallService(InstallHostSettings settings, Action<InstallHostSettings> beforeInstall, Action afterInstall, Action beforeRollback, Action afterRollback);
/// <summary>
/// Uninstall the service using the settings provided
/// </summary>
/// <param name="settings"></param>
/// <param name="beforeUninstall"></param>
/// <param name="afterUninstall"></param>
void UninstallService(HostSettings settings, Action beforeUninstall, Action afterUninstall);
/// <summary>
/// Restarts the service as an administrator which has permission to modify the service configuration
/// </summary>
/// <returns>True if the child process was executed, otherwise false</returns>
bool RunAsAdministrator();
/// <summary>
/// Create a service host appropriate for the host environment
/// </summary>
/// <param name="settings"></param>
/// <param name="serviceHandle"></param>
/// <returns></returns>
Host CreateServiceHost(HostSettings settings, ServiceHandle serviceHandle);
/// <summary>
/// Send a command to a service to make it do something
/// </summary>
/// <param name="serviceName">The service name</param>
/// <param name="command">The command value</param>
void SendServiceCommand(string serviceName, int command);
}
}

@ -1,96 +0,0 @@
using System;
namespace ZeroLevel.Services.AsService
{
public enum UnhandledExceptionPolicyCode
{
/// <summary>
/// If an UnhandledException occurs, AsService will log an error and
/// stop the service
/// </summary>
LogErrorAndStopService = 0,
/// <summary>
/// If an UnhandledException occurs, AsService will log an error and
/// continue without stopping the service
/// </summary>
LogErrorOnly = 1,
/// <summary>
/// If an UnhandledException occurs, AsService will take no action.
/// It is assumed that the application will handle the UnhandledException itself.
/// </summary>
TakeNoAction = 2
}
/// <summary>
/// The settings that have been configured for the operating system service
/// </summary>
public interface HostSettings
{
/// <summary>
/// The name of the service
/// </summary>
string Name { get; }
/// <summary>
/// The name of the service as it should be displayed in the service control manager
/// </summary>
string DisplayName { get; }
/// <summary>
/// The description of the service that is displayed in the service control manager
/// </summary>
string Description { get; }
/// <summary>
/// The service instance name that should be used when the service is registered
/// </summary>
string InstanceName { get; }
/// <summary>
/// Returns the Windows service name, including the instance name, which is registered with the SCM Example: myservice$bob
/// </summary>
/// <returns> </returns>
string ServiceName { get; }
/// <summary>
/// True if the service supports pause and continue
/// </summary>
bool CanPauseAndContinue { get; }
/// <summary>
/// True if the service can handle the shutdown event
/// </summary>
bool CanShutdown { get; }
/// <summary>
/// True if the service handles session change events
/// </summary>
bool CanSessionChanged { get; }
/// <summary>
/// True if the service handles power change events
/// </summary>
bool CanHandlePowerEvent { get; }
/// <summary>
/// The amount of time to wait for the service to start before timing out. Default is 10 seconds.
/// </summary>
TimeSpan StartTimeOut { get; }
/// <summary>
/// The amount of time to wait for the service to stop before timing out. Default is 10 seconds.
/// </summary>
TimeSpan StopTimeOut { get; }
/// <summary>
/// A callback to provide visibility into exceptions while AsService is performing its
/// own handling.
/// </summary>
Action<Exception> ExceptionCallback { get; }
/// <summary>
/// The policy that will be used when Topself detects an UnhandledException in the
/// application. The default policy is to log an error and to stop the service.
/// </summary>
UnhandledExceptionPolicyCode UnhandledExceptionPolicy { get; }
}
}

@ -1,10 +0,0 @@
namespace ZeroLevel.Services.AsService
{
public enum HostStartMode
{
Automatic = 0,
Manual = 1,
Disabled = 2,
AutomaticDelayed = 3,
}
}

@ -1,20 +0,0 @@
using System.ComponentModel;
namespace ZeroLevel.Services.AsService
{
public abstract class ComponentInstaller
: Installer
{
/// <summary>When overridden in a derived class, copies all the properties that are required at install time from the specified component.</summary>
/// <param name="component">The component to copy from. </param>
public abstract void CopyFromComponent(IComponent component);
/// <summary>Determines if the specified installer installs the same object as this installer.</summary>
/// <returns>true if this installer and the installer specified by the <paramref name="otherInstaller" /> parameter install the same object; otherwise, false.</returns>
/// <param name="otherInstaller">The installer to compare. </param>
public virtual bool IsEquivalentInstaller(ComponentInstaller otherInstaller)
{
return false;
}
}
}

@ -1,116 +0,0 @@
using System;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Text;
namespace ZeroLevel.Services.AsService
{
public class InstallContext
{
private StringDictionary parameters;
public StringDictionary Parameters => this.parameters;
public InstallContext() : this(null, null)
{
}
public InstallContext(string logFilePath, string[] commandLine)
{
this.parameters = InstallContext.ParseCommandLine(commandLine);
if (this.Parameters["logfile"] == null && logFilePath != null)
{
this.Parameters["logfile"] = logFilePath;
}
}
public bool IsParameterTrue(string paramName)
{
string text = this.Parameters[paramName.ToLower(CultureInfo.InvariantCulture)];
if (text == null)
{
return false;
}
if (string.Compare(text, "true", StringComparison.OrdinalIgnoreCase) != 0
&& string.Compare(text, "yes", StringComparison.OrdinalIgnoreCase) != 0
&& string.Compare(text, "1", StringComparison.OrdinalIgnoreCase) != 0)
{
return "".Equals(text);
}
return true;
}
public void LogMessage(string message)
{
try
{
this.LogMessageHelper(message);
}
catch (Exception)
{
try
{
this.Parameters["logfile"] = Path.Combine(Path.GetTempPath(), Path.GetFileName(this.Parameters["logfile"]));
this.LogMessageHelper(message);
}
catch (Exception)
{
this.Parameters["logfile"] = null;
}
}
if (!this.IsParameterTrue("LogToConsole") && this.Parameters["logtoconsole"] != null)
{
return;
}
Console.WriteLine(message);
}
internal void LogMessageHelper(string message)
{
StreamWriter streamWriter = null;
try
{
if (!string.IsNullOrEmpty(this.Parameters["logfile"]))
{
streamWriter = new StreamWriter(this.Parameters["logfile"], true, Encoding.UTF8);
streamWriter.WriteLine(message);
}
}
finally
{
if (streamWriter != null)
{
streamWriter.Close();
}
}
}
protected static StringDictionary ParseCommandLine(string[] args)
{
StringDictionary stringDictionary = new StringDictionary();
if (args == null)
{
return stringDictionary;
}
for (int i = 0; i < args.Length; i++)
{
if (args[i].StartsWith("/", StringComparison.Ordinal) || args[i].StartsWith("-", StringComparison.Ordinal))
{
args[i] = args[i].Substring(1);
}
int num = args[i].IndexOf('=');
if (num < 0)
{
stringDictionary[args[i].ToLower(CultureInfo.InvariantCulture)] = "";
}
else
{
stringDictionary[args[i].Substring(0, num).ToLower(CultureInfo.InvariantCulture)] = args[i].Substring(num + 1);
}
}
return stringDictionary;
}
}
}

@ -1,20 +0,0 @@
using System.Collections;
namespace ZeroLevel.Services.AsService
{
public delegate void InstallEventHandler(object sender, InstallEventArgs e);
public class InstallEventArgs
{
public IDictionary SavedSate { get; }
public InstallEventArgs()
{
}
public InstallEventArgs(IDictionary savedSate)
{
this.SavedSate = savedSate;
}
}
}

@ -1,26 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace ZeroLevel.Services.AsService
{
[Serializable]
internal class InstallException : SystemException
{
public InstallException()
{
base.HResult = -2146232057;
}
public InstallException(string message) : base(message)
{
}
public InstallException(string message, Exception innerException) : base(message, innerException)
{
}
protected InstallException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}

@ -1,10 +0,0 @@
namespace ZeroLevel.Services.AsService
{
public interface InstallHostSettings :
HostSettings
{
Credentials Credentials { get; set; }
string[] Dependencies { get; }
HostStartMode StartMode { get; }
}
}

@ -1,573 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace ZeroLevel.Services.AsService
{
public class Installer : System.ComponentModel.Component
{
internal Installer parent;
private InstallerCollection installers;
public InstallContext Context { get; set; }
public InstallerCollection Installers
{
get
{
if (this.installers == null)
{
this.installers = new InstallerCollection(this);
}
return this.installers;
}
}
[ResDescription("Desc_Installer_HelpText")]
public virtual string HelpText
{
get
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < this.Installers.Count; i++)
{
string helpText = this.Installers[i].HelpText;
if (helpText.Length > 0)
{
stringBuilder.Append("\r\n");
stringBuilder.Append(helpText);
}
}
return stringBuilder.ToString();
}
}
[TypeConverter(typeof(InstallerParentConverter))]
[ResDescription("Desc_Installer_Parent")]
public Installer Parent
{
get
{
return this.parent;
}
set
{
if (value == this)
{
throw new InvalidOperationException(Res.GetString("InstallBadParent"));
}
if (value != this.parent)
{
if (value != null && this.InstallerTreeContains(value))
{
throw new InvalidOperationException(Res.GetString("InstallRecursiveParent"));
}
if (this.parent != null)
{
int num = this.parent.Installers.IndexOf(this);
if (num != -1)
{
this.parent.Installers.RemoveAt(num);
}
}
this.parent = value;
if (this.parent != null && !this.parent.Installers.Contains(this))
{
this.parent.Installers.Add(this);
}
}
}
}
public virtual void Commit(IDictionary savedState)
{
if (savedState == null)
{
throw new ArgumentException(Res.GetString("InstallNullParameter", "savedState"));
}
if (savedState["_reserved_lastInstallerAttempted"] != null && savedState["_reserved_nestedSavedStates"] != null)
{
Exception ex = null;
try
{
this.OnCommitting(savedState);
}
catch (Exception ex2)
{
this.WriteEventHandlerError(Res.GetString("InstallSeverityWarning"), "OnCommitting", ex2);
this.Context.LogMessage(Res.GetString("InstallCommitException"));
ex = ex2;
}
int num = (int)savedState["_reserved_lastInstallerAttempted"];
IDictionary[] array = (IDictionary[])savedState["_reserved_nestedSavedStates"];
if (num + 1 == array.Length && num < this.Installers.Count)
{
for (int i = 0; i < this.Installers.Count; i++)
{
this.Installers[i].Context = this.Context;
}
for (int j = 0; j <= num; j++)
{
try
{
this.Installers[j].Commit(array[j]);
}
catch (Exception ex3)
{
if (!this.IsWrappedException(ex3))
{
this.Context.LogMessage(Res.GetString("InstallLogCommitException", this.Installers[j].ToString()));
Installer.LogException(ex3, this.Context);
this.Context.LogMessage(Res.GetString("InstallCommitException"));
}
ex = ex3;
}
}
savedState["_reserved_nestedSavedStates"] = array;
savedState.Remove("_reserved_lastInstallerAttempted");
try
{
this.OnCommitted(savedState);
}
catch (Exception ex4)
{
this.WriteEventHandlerError(Res.GetString("InstallSeverityWarning"), "OnCommitted", ex4);
this.Context.LogMessage(Res.GetString("InstallCommitException"));
ex = ex4;
}
if (ex == null)
{
return;
}
Exception ex5 = ex;
if (!this.IsWrappedException(ex))
{
ex5 = new InstallException(Res.GetString("InstallCommitException"), ex);
ex5.Source = "WrappedExceptionSource";
}
throw ex5;
}
throw new ArgumentException(Res.GetString("InstallDictionaryCorrupted", "savedState"));
}
throw new ArgumentException(Res.GetString("InstallDictionaryMissingValues", "savedState"));
}
public virtual void Install(IDictionary stateSaver)
{
if (stateSaver == null)
{
throw new ArgumentNullException(nameof(stateSaver));
}
try
{
this.OnBeforeInstall(stateSaver);
}
catch (Exception ex)
{
this.WriteEventHandlerError(Res.GetString("InstallSeverityError"), "OnBeforeInstall", ex);
throw new InvalidOperationException(Res.GetString("InstallEventException", "OnBeforeInstall", base.GetType().FullName), ex);
}
int num = -1;
List<IDictionary> arrayList = new List<IDictionary>();
try
{
for (int i = 0; i < this.Installers.Count; i++)
{
this.Installers[i].Context = this.Context;
}
for (int j = 0; j < this.Installers.Count; j++)
{
Installer installer = this.Installers[j];
IDictionary dictionary = new Hashtable();
try
{
num = j;
installer.Install(dictionary);
}
finally
{
arrayList.Add(dictionary);
}
}
}
finally
{
stateSaver.Add("_reserved_lastInstallerAttempted", num);
stateSaver.Add("_reserved_nestedSavedStates", arrayList.ToArray());
}
try
{
this.OnAfterInstall(stateSaver);
}
catch (Exception ex2)
{
this.WriteEventHandlerError(Res.GetString("InstallSeverityError"), "OnAfterInstall", ex2);
throw new InvalidOperationException(Res.GetString("InstallEventException", "OnAfterInstall", base.GetType().FullName), ex2);
}
}
public virtual void Rollback(IDictionary savedState)
{
if (savedState == null)
{
throw new ArgumentException(Res.GetString("InstallNullParameter", "savedState"));
}
if (savedState["_reserved_lastInstallerAttempted"] != null && savedState["_reserved_nestedSavedStates"] != null)
{
Exception ex = null;
try
{
this.OnBeforeRollback(savedState);
}
catch (Exception ex2)
{
this.WriteEventHandlerError(Res.GetString("InstallSeverityWarning"), "OnBeforeRollback", ex2);
this.Context.LogMessage(Res.GetString("InstallRollbackException"));
ex = ex2;
}
int num = (int)savedState["_reserved_lastInstallerAttempted"];
IDictionary[] array = (IDictionary[])savedState["_reserved_nestedSavedStates"];
if (num + 1 == array.Length && num < this.Installers.Count)
{
for (int num2 = this.Installers.Count - 1; num2 >= 0; num2--)
{
this.Installers[num2].Context = this.Context;
}
for (int num3 = num; num3 >= 0; num3--)
{
try
{
this.Installers[num3].Rollback(array[num3]);
}
catch (Exception ex3)
{
if (!this.IsWrappedException(ex3))
{
this.Context.LogMessage(Res.GetString("InstallLogRollbackException", this.Installers[num3].ToString()));
Installer.LogException(ex3, this.Context);
this.Context.LogMessage(Res.GetString("InstallRollbackException"));
}
ex = ex3;
}
}
try
{
this.OnAfterRollback(savedState);
}
catch (Exception ex4)
{
this.WriteEventHandlerError(Res.GetString("InstallSeverityWarning"), "OnAfterRollback", ex4);
this.Context.LogMessage(Res.GetString("InstallRollbackException"));
ex = ex4;
}
if (ex == null)
{
return;
}
Exception ex5 = ex;
if (!this.IsWrappedException(ex))
{
ex5 = new InstallException(Res.GetString("InstallRollbackException"), ex);
ex5.Source = "WrappedExceptionSource";
}
throw ex5;
}
throw new ArgumentException(Res.GetString("InstallDictionaryCorrupted", "savedState"));
}
throw new ArgumentException(Res.GetString("InstallDictionaryMissingValues", "savedState"));
}
public virtual void Uninstall(IDictionary savedState)
{
Exception ex = null;
try
{
this.OnBeforeUninstall(savedState);
}
catch (Exception ex2)
{
this.WriteEventHandlerError(Res.GetString("InstallSeverityWarning"), "OnBeforeUninstall", ex2);
this.Context.LogMessage(Res.GetString("InstallUninstallException"));
ex = ex2;
}
IDictionary[] array;
if (savedState != null)
{
array = (IDictionary[])savedState["_reserved_nestedSavedStates"];
if (array != null && array.Length == this.Installers.Count)
{
goto IL_0091;
}
throw new ArgumentException(Res.GetString("InstallDictionaryCorrupted", "savedState"));
}
array = new IDictionary[this.Installers.Count];
goto IL_0091;
IL_0091:
for (int num = this.Installers.Count - 1; num >= 0; num--)
{
this.Installers[num].Context = this.Context;
}
for (int num2 = this.Installers.Count - 1; num2 >= 0; num2--)
{
try
{
this.Installers[num2].Uninstall(array[num2]);
}
catch (Exception ex3)
{
if (!this.IsWrappedException(ex3))
{
this.Context.LogMessage(Res.GetString("InstallLogUninstallException", this.Installers[num2].ToString()));
Installer.LogException(ex3, this.Context);
this.Context.LogMessage(Res.GetString("InstallUninstallException"));
}
ex = ex3;
}
}
try
{
this.OnAfterUninstall(savedState);
}
catch (Exception ex4)
{
this.WriteEventHandlerError(Res.GetString("InstallSeverityWarning"), "OnAfterUninstall", ex4);
this.Context.LogMessage(Res.GetString("InstallUninstallException"));
ex = ex4;
}
if (ex == null)
{
return;
}
Exception ex5 = ex;
if (!this.IsWrappedException(ex))
{
ex5 = new InstallException(Res.GetString("InstallUninstallException"), ex);
ex5.Source = "WrappedExceptionSource";
}
throw ex5;
}
#region Event Handlers
private InstallEventHandler afterCommitHandler;
private InstallEventHandler afterInstallHandler;
private InstallEventHandler afterRollbackHandler;
private InstallEventHandler afterUninstallHandler;
private InstallEventHandler beforeCommitHandler;
private InstallEventHandler beforeInstallHandler;
private InstallEventHandler beforeRollbackHandler;
private InstallEventHandler beforeUninstallHandler;
public event InstallEventHandler Committed
{
add
{
this.afterCommitHandler = (InstallEventHandler)Delegate.Combine(this.afterCommitHandler, value);
}
remove
{
this.afterCommitHandler = (InstallEventHandler)Delegate.Remove(this.afterCommitHandler, value);
}
}
/// <summary>Occurs after the <see cref="M:System.Configuration.Install.Installer.Install(System.Collections.IDictionary)" /> methods of all the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property have run.</summary>
public event InstallEventHandler AfterInstall
{
add
{
this.afterInstallHandler = (InstallEventHandler)Delegate.Combine(this.afterInstallHandler, value);
}
remove
{
this.afterInstallHandler = (InstallEventHandler)Delegate.Remove(this.afterInstallHandler, value);
}
}
/// <summary>Occurs after the installations of all the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property are rolled back.</summary>
public event InstallEventHandler AfterRollback
{
add
{
this.afterRollbackHandler = (InstallEventHandler)Delegate.Combine(this.afterRollbackHandler, value);
}
remove
{
this.afterRollbackHandler = (InstallEventHandler)Delegate.Remove(this.afterRollbackHandler, value);
}
}
/// <summary>Occurs after all the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property perform their uninstallation operations.</summary>
public event InstallEventHandler AfterUninstall
{
add
{
this.afterUninstallHandler = (InstallEventHandler)Delegate.Combine(this.afterUninstallHandler, value);
}
remove
{
this.afterUninstallHandler = (InstallEventHandler)Delegate.Remove(this.afterUninstallHandler, value);
}
}
/// <summary>Occurs before the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property committ their installations.</summary>
public event InstallEventHandler Committing
{
add
{
this.beforeCommitHandler = (InstallEventHandler)Delegate.Combine(this.beforeCommitHandler, value);
}
remove
{
this.beforeCommitHandler = (InstallEventHandler)Delegate.Remove(this.beforeCommitHandler, value);
}
}
/// <summary>Occurs before the <see cref="M:System.Configuration.Install.Installer.Install(System.Collections.IDictionary)" /> method of each installer in the installer collection has run.</summary>
public event InstallEventHandler BeforeInstall
{
add
{
this.beforeInstallHandler = (InstallEventHandler)Delegate.Combine(this.beforeInstallHandler, value);
}
remove
{
this.beforeInstallHandler = (InstallEventHandler)Delegate.Remove(this.beforeInstallHandler, value);
}
}
/// <summary>Occurs before the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property are rolled back.</summary>
public event InstallEventHandler BeforeRollback
{
add
{
this.beforeRollbackHandler = (InstallEventHandler)Delegate.Combine(this.beforeRollbackHandler, value);
}
remove
{
this.beforeRollbackHandler = (InstallEventHandler)Delegate.Remove(this.beforeRollbackHandler, value);
}
}
/// <summary>Occurs before the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property perform their uninstall operations.</summary>
public event InstallEventHandler BeforeUninstall
{
add
{
this.beforeUninstallHandler = (InstallEventHandler)Delegate.Combine(this.beforeUninstallHandler, value);
}
remove
{
this.beforeUninstallHandler = (InstallEventHandler)Delegate.Remove(this.beforeUninstallHandler, value);
}
}
protected virtual void OnCommitted(IDictionary savedState)
{
this.afterCommitHandler?.Invoke(this, new InstallEventArgs(savedState));
}
/// <summary>Raises the <see cref="E:System.Configuration.Install.Installer.AfterInstall" /> event.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the state of the computer after all the installers contained in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property have completed their installations. </param>
protected virtual void OnAfterInstall(IDictionary savedState)
{
this.afterInstallHandler?.Invoke(this, new InstallEventArgs(savedState));
}
/// <summary>Raises the <see cref="E:System.Configuration.Install.Installer.AfterRollback" /> event.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the state of the computer after the installers contained in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property are rolled back. </param>
protected virtual void OnAfterRollback(IDictionary savedState)
{
this.afterRollbackHandler?.Invoke(this, new InstallEventArgs(savedState));
}
/// <summary>Raises the <see cref="E:System.Configuration.Install.Installer.AfterUninstall" /> event.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the state of the computer after all the installers contained in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property are uninstalled. </param>
protected virtual void OnAfterUninstall(IDictionary savedState)
{
this.afterUninstallHandler?.Invoke(this, new InstallEventArgs(savedState));
}
/// <summary>Raises the <see cref="E:System.Configuration.Install.Installer.Committing" /> event.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the state of the computer before the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property are committed. </param>
protected virtual void OnCommitting(IDictionary savedState)
{
this.beforeCommitHandler?.Invoke(this, new InstallEventArgs(savedState));
}
/// <summary>Raises the <see cref="E:System.Configuration.Install.Installer.BeforeInstall" /> event.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the state of the computer before the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property are installed. This <see cref="T:System.Collections.IDictionary" /> object should be empty at this point. </param>
protected virtual void OnBeforeInstall(IDictionary savedState)
{
this.beforeInstallHandler?.Invoke(this, new InstallEventArgs(savedState));
}
/// <summary>Raises the <see cref="E:System.Configuration.Install.Installer.BeforeRollback" /> event.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the state of the computer before the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property are rolled back. </param>
protected virtual void OnBeforeRollback(IDictionary savedState)
{
this.beforeRollbackHandler?.Invoke(this, new InstallEventArgs(savedState));
}
/// <summary>Raises the <see cref="E:System.Configuration.Install.Installer.BeforeUninstall" /> event.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the state of the computer before the installers in the <see cref="P:System.Configuration.Install.Installer.Installers" /> property uninstall their installations. </param>
protected virtual void OnBeforeUninstall(IDictionary savedState)
{
this.beforeUninstallHandler?.Invoke(this, new InstallEventArgs(savedState));
}
#endregion
private void WriteEventHandlerError(string severity, string eventName, Exception e)
{
this.Context.LogMessage(Res.GetString("InstallLogError", severity, eventName, base.GetType().FullName));
Installer.LogException(e, this.Context);
}
internal static void LogException(Exception e, InstallContext context)
{
bool flag = true;
while (e != null)
{
if (flag)
{
context.LogMessage(e.GetType().FullName + ": " + e.Message);
flag = false;
}
else
{
context.LogMessage(Res.GetString("InstallLogInner", e.GetType().FullName, e.Message));
}
if (context.IsParameterTrue("showcallstack"))
{
context.LogMessage(e.StackTrace);
}
e = e.InnerException;
}
}
private bool IsWrappedException(Exception e)
{
if (e is InstallException && e.Source == "WrappedExceptionSource")
{
return e.TargetSite.ReflectedType == typeof(Installer);
}
return false;
}
internal bool InstallerTreeContains(Installer target)
{
if (this.Installers.Contains(target))
{
return true;
}
foreach (Installer installer in this.Installers)
{
if (installer.InstallerTreeContains(target))
{
return true;
}
}
return false;
}
}
}

@ -1,57 +0,0 @@
using System;
using System.Collections.Generic;
namespace ZeroLevel.Services.AsService
{
public class InstallerCollection
: System.Collections.ObjectModel.Collection<Installer>
{
private readonly Installer owner;
internal InstallerCollection(Installer owner)
{
this.owner = owner;
}
public void AddRange(IEnumerable<Installer> value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
foreach (var item in value)
{
this.Add(item);
}
}
protected override void InsertItem(int index, Installer item)
{
if (item == this.owner)
{
throw new ArgumentException(Res.GetString("CantAddSelf"));
}
item.parent = this.owner;
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
this[index].parent = null;
base.RemoveItem(index);
}
protected override void SetItem(int index, Installer item)
{
if (item == this.owner)
{
throw new ArgumentException(Res.GetString("CantAddSelf"));
}
this[index].parent = null;
item.parent = owner;
base.SetItem(index, item);
}
}
}

@ -1,32 +0,0 @@
using System;
using System.ComponentModel;
namespace ZeroLevel.Services.AsService
{
internal class InstallerParentConverter
: ReferenceConverter
{
public InstallerParentConverter(Type type)
: base(type)
{
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
StandardValuesCollection standardValues = base.GetStandardValues(context);
object instance = context.Instance;
int i = 0;
int num = 0;
object[] array = new object[standardValues.Count - 1];
for (; i < standardValues.Count; i++)
{
if (standardValues[i] != instance)
{
array[num] = standardValues[i];
num++;
}
}
return new StandardValuesCollection(array);
}
}
}

@ -1,493 +0,0 @@
using System;
using System.Text;
using System.ServiceProcess;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Collections;
using System.Threading;
namespace ZeroLevel.Services.AsService
{
public class ServiceInstaller
: ComponentInstaller
{
private const string NetworkServiceName = "NT AUTHORITY\\NetworkService";
private const string LocalServiceName = "NT AUTHORITY\\LocalService";
//private EventLogInstaller eventLogInstaller;
private string serviceName = "";
private string displayName = "";
private string description = "";
private string[] servicesDependedOn = new string[0];
private ServiceStartMode startType = ServiceStartMode.Manual;
private bool delayedStartMode;
private static bool environmentChecked;
private static bool isWin9x;
/// <summary>Indicates the friendly name that identifies the service to the user.</summary>
/// <returns>The name associated with the service, used frequently for interactive tools.</returns>
[DefaultValue("")]
[ServiceProcessDescription("ServiceInstallerDisplayName")]
public string DisplayName
{
get
{
return this.displayName;
}
set
{
if (value == null)
{
value = "";
}
this.displayName = value;
}
}
/// <summary>Gets or sets the description for the service.</summary>
/// <returns>The description of the service. The default is an empty string ("").</returns>
[DefaultValue("")]
[ComVisible(false)]
[ServiceProcessDescription("ServiceInstallerDescription")]
public string Description
{
get
{
return this.description;
}
set
{
if (value == null)
{
value = "";
}
this.description = value;
}
}
/// <summary>Indicates the services that must be running for this service to run.</summary>
/// <returns>An array of services that must be running before the service associated with this installer can run.</returns>
[ServiceProcessDescription("ServiceInstallerServicesDependedOn")]
public string[] ServicesDependedOn
{
get
{
return this.servicesDependedOn;
}
set
{
if (value == null)
{
value = new string[0];
}
this.servicesDependedOn = value;
}
}
/// <summary>Indicates the name used by the system to identify this service. This property must be identical to the <see cref="P:System.ServiceProcess.ServiceBase.ServiceName" /> of the service you want to install.</summary>
/// <returns>The name of the service to be installed. This value must be set before the install utility attempts to install the service.</returns>
/// <exception cref="T:System.ArgumentException">The <see cref="P:System.ServiceProcess.ServiceInstaller.ServiceName" /> property is invalid. </exception>
[DefaultValue("")]
[TypeConverter("System.Diagnostics.Design.StringValueConverter, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[ServiceProcessDescription("ServiceInstallerServiceName")]
public string ServiceName
{
get
{
return this.serviceName;
}
set
{
if (value == null)
{
value = "";
}
if (!ServiceControllerExtensions.ValidServiceName(value))
{
throw new ArgumentException(Res.GetString("ServiceName", value, 80.ToString(CultureInfo.CurrentCulture)));
}
this.serviceName = value;
//this.eventLogInstaller.Source = value;
}
}
/// <summary>Indicates how and when this service is started.</summary>
/// <returns>A <see cref="T:System.ServiceProcess.ServiceStartMode" /> that represents the way the service is started. The default is Manual, which specifies that the service will not automatically start after reboot.</returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">The start mode is not a value of the <see cref="T:System.ServiceProcess.ServiceStartMode" /> enumeration.</exception>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
/// </PermissionSet>
[DefaultValue(ServiceStartMode.Manual)]
[ServiceProcessDescription("ServiceInstallerStartType")]
public ServiceStartMode StartType
{
get
{
return this.startType;
}
set
{
if (!Enum.IsDefined(typeof(ServiceStartMode), value))
{
throw new InvalidEnumArgumentException("value", (int)value, typeof(ServiceStartMode));
}
if (value != 0 && value != ServiceStartMode.System)
{
this.startType = value;
return;
}
throw new ArgumentException(Res.GetString("ServiceStartType", value));
}
}
/// <summary>Gets or sets a value that indicates whether the service should be delayed from starting until other automatically started services are running.</summary>
/// <returns>true to delay automatic start of the service; otherwise, false. The default is false.</returns>
[DefaultValue(false)]
[ServiceProcessDescription("ServiceInstallerDelayedAutoStart")]
public bool DelayedAutoStart
{
get
{
return this.delayedStartMode;
}
set
{
this.delayedStartMode = value;
}
}
/// <summary>Initializes a new instance of the <see cref="T:System.ServiceProcess.ServiceInstaller" /> class.</summary>
public ServiceInstaller()
{
//this.eventLogInstaller = new EventLogInstaller();
//this.eventLogInstaller.Log = "Application";
//this.eventLogInstaller.Source = "";
//this.eventLogInstaller.UninstallAction = UninstallAction.Remove;
//base.Installers.Add(this.eventLogInstaller);
}
internal static void CheckEnvironment()
{
if (ServiceInstaller.environmentChecked)
{
if (!ServiceInstaller.isWin9x)
{
return;
}
throw new PlatformNotSupportedException(Res.GetString("CantControlOnWin9x"));
}
ServiceInstaller.isWin9x = (Environment.OSVersion.Platform != PlatformID.Win32NT);
ServiceInstaller.environmentChecked = true;
if (!ServiceInstaller.isWin9x)
{
return;
}
throw new PlatformNotSupportedException(Res.GetString("CantInstallOnWin9x"));
}
/// <summary>Copies properties from an instance of <see cref="T:System.ServiceProcess.ServiceBase" /> to this installer.</summary>
/// <param name="component">The <see cref="T:System.ComponentModel.IComponent" /> from which to copy. </param>
/// <exception cref="T:System.ArgumentException">The component you are associating with this installer does not inherit from <see cref="T:System.ServiceProcess.ServiceBase" />. </exception>
public override void CopyFromComponent(IComponent component)
{
if (!(component is ServiceBase))
{
throw new ArgumentException(Res.GetString("NotAService"));
}
ServiceBase serviceBase = (ServiceBase)component;
this.ServiceName = serviceBase.ServiceName;
}
/// <summary>Installs the service by writing service application information to the registry. This method is meant to be used by installation tools, which process the appropriate methods automatically.</summary>
/// <param name="stateSaver">An <see cref="T:System.Collections.IDictionary" /> that contains the context information associated with the installation. </param>
/// <exception cref="T:System.InvalidOperationException">The installation does not contain a <see cref="T:System.ServiceProcess.ServiceProcessInstaller" /> for the executable.-or- The file name for the assembly is null or an empty string.-or- The service name is invalid.-or- The Service Control Manager could not be opened. </exception>
/// <exception cref="T:System.ArgumentException">The display name for the service is more than 255 characters in length.</exception>
/// <exception cref="T:System.ComponentModel.Win32Exception">The system could not generate a handle to the service. -or-A service with that name is already installed.</exception>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" />
/// <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
public override void Install(IDictionary stateSaver)
{
base.Context.LogMessage(Res.GetString("InstallingService", this.ServiceName));
try
{
ServiceInstaller.CheckEnvironment();
string servicesStartName = null;
string password = null;
ServiceProcessInstaller serviceProcessInstaller = null;
if (base.Parent is ServiceProcessInstaller)
{
serviceProcessInstaller = (ServiceProcessInstaller)base.Parent;
}
else
{
int num = 0;
while (num < base.Parent.Installers.Count)
{
if (!(base.Parent.Installers[num] is ServiceProcessInstaller))
{
num++;
continue;
}
serviceProcessInstaller = (ServiceProcessInstaller)base.Parent.Installers[num];
break;
}
}
if (serviceProcessInstaller == null)
{
throw new InvalidOperationException(Res.GetString("NoInstaller"));
}
switch (serviceProcessInstaller.Account)
{
case ServiceAccount.LocalService:
servicesStartName = "NT AUTHORITY\\LocalService";
break;
case ServiceAccount.NetworkService:
servicesStartName = "NT AUTHORITY\\NetworkService";
break;
case ServiceAccount.User:
servicesStartName = serviceProcessInstaller.Username;
password = serviceProcessInstaller.Password;
break;
}
string text = base.Context.Parameters["assemblypath"];
if (string.IsNullOrEmpty(text))
{
throw new InvalidOperationException(Res.GetString("FileName"));
}
if (text.IndexOf('"') == -1)
{
text = "\"" + text + "\"";
}
if (!ServiceInstaller.ValidateServiceName(this.ServiceName))
{
throw new InvalidOperationException(Res.GetString("ServiceName", this.ServiceName, 80.ToString(CultureInfo.CurrentCulture)));
}
if (this.DisplayName.Length > 255)
{
throw new ArgumentException(Res.GetString("DisplayNameTooLong", this.DisplayName));
}
string dependencies = null;
if (this.ServicesDependedOn.Length != 0)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < this.ServicesDependedOn.Length; i++)
{
string text2 = this.ServicesDependedOn[i];
try
{
text2 = new ServiceController(text2, ".").ServiceName;
}
catch
{
}
stringBuilder.Append(text2);
stringBuilder.Append('\0');
}
stringBuilder.Append('\0');
dependencies = stringBuilder.ToString();
}
IntPtr intPtr = SafeNativeMethods.OpenSCManager(null, null, 983103);
IntPtr intPtr2 = IntPtr.Zero;
if (intPtr == IntPtr.Zero)
{
throw new InvalidOperationException(Res.GetString("OpenSC", "."), new Win32Exception());
}
int serviceType = 16;
int num2 = 0;
for (int j = 0; j < base.Parent.Installers.Count; j++)
{
if (base.Parent.Installers[j] is ServiceInstaller)
{
num2++;
if (num2 > 1)
{
break;
}
}
}
if (num2 > 1)
{
serviceType = 32;
}
try
{
intPtr2 = NativeMethods.CreateService(intPtr, this.ServiceName, this.DisplayName, 983551, serviceType, (int)this.StartType, 1, text, null, IntPtr.Zero, dependencies, servicesStartName, password);
if (intPtr2 == IntPtr.Zero)
{
throw new Win32Exception();
}
if (this.Description.Length != 0)
{
NativeMethods.SERVICE_DESCRIPTION sERVICE_DESCRIPTION = default(NativeMethods.SERVICE_DESCRIPTION);
sERVICE_DESCRIPTION.description = Marshal.StringToHGlobalUni(this.Description);
bool num3 = NativeMethods.ChangeServiceConfig2(intPtr2, 1u, ref sERVICE_DESCRIPTION);
Marshal.FreeHGlobal(sERVICE_DESCRIPTION.description);
if (!num3)
{
throw new Win32Exception();
}
}
if (Environment.OSVersion.Version.Major > 5 && this.StartType == ServiceStartMode.Automatic)
{
NativeMethods.SERVICE_DELAYED_AUTOSTART_INFO sERVICE_DELAYED_AUTOSTART_INFO = default(NativeMethods.SERVICE_DELAYED_AUTOSTART_INFO);
sERVICE_DELAYED_AUTOSTART_INFO.fDelayedAutostart = this.DelayedAutoStart;
if (!NativeMethods.ChangeServiceConfig2(intPtr2, 3u, ref sERVICE_DELAYED_AUTOSTART_INFO))
{
throw new Win32Exception();
}
}
stateSaver["installed"] = true;
}
finally
{
if (intPtr2 != IntPtr.Zero)
{
SafeNativeMethods.CloseServiceHandle(intPtr2);
}
SafeNativeMethods.CloseServiceHandle(intPtr);
}
base.Context.LogMessage(Res.GetString("InstallOK", this.ServiceName));
}
finally
{
base.Install(stateSaver);
}
}
/// <summary>Indicates whether two installers would install the same service.</summary>
/// <returns>true if calling <see cref="M:System.ServiceProcess.ServiceInstaller.Install(System.Collections.IDictionary)" /> on both of these installers would result in installing the same service; otherwise, false.</returns>
/// <param name="otherInstaller">A <see cref="T:System.Configuration.Install.ComponentInstaller" /> to which you are comparing the current installer. </param>
public override bool IsEquivalentInstaller(ComponentInstaller otherInstaller)
{
ServiceInstaller serviceInstaller = otherInstaller as ServiceInstaller;
if (serviceInstaller == null)
{
return false;
}
return serviceInstaller.ServiceName == this.ServiceName;
}
private void RemoveService()
{
base.Context.LogMessage(Res.GetString("ServiceRemoving", this.ServiceName));
IntPtr intPtr = SafeNativeMethods.OpenSCManager(null, null, 983103);
if (intPtr == IntPtr.Zero)
{
throw new Win32Exception();
}
IntPtr intPtr2 = IntPtr.Zero;
try
{
intPtr2 = NativeMethods.OpenService(intPtr, this.ServiceName, 65536);
if (intPtr2 == IntPtr.Zero)
{
throw new Win32Exception();
}
NativeMethods.DeleteService(intPtr2);
}
finally
{
if (intPtr2 != IntPtr.Zero)
{
SafeNativeMethods.CloseServiceHandle(intPtr2);
}
SafeNativeMethods.CloseServiceHandle(intPtr);
}
base.Context.LogMessage(Res.GetString("ServiceRemoved", this.ServiceName));
try
{
using (ServiceController serviceController = new ServiceController(this.ServiceName))
{
if (serviceController.Status != ServiceControllerStatus.Stopped)
{
base.Context.LogMessage(Res.GetString("TryToStop", this.ServiceName));
serviceController.Stop();
int num = 10;
serviceController.Refresh();
while (serviceController.Status != ServiceControllerStatus.Stopped && num > 0)
{
Thread.Sleep(1000);
serviceController.Refresh();
num--;
}
}
}
}
catch
{
}
Thread.Sleep(5000);
}
/// <summary>Rolls back service application information written to the registry by the installation procedure. This method is meant to be used by installation tools, which process the appropriate methods automatically.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the context information associated with the installation. </param>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" />
/// <IPermission class="System.ServiceProcess.ServiceControllerPermission, System.ServiceProcess, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" version="1" Unrestricted="true" />
/// </PermissionSet>
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
object obj = savedState["installed"];
if (obj != null && (bool)obj)
{
this.RemoveService();
}
}
private bool ShouldSerializeServicesDependedOn()
{
if (this.servicesDependedOn != null && this.servicesDependedOn.Length != 0)
{
return true;
}
return false;
}
/// <summary>Uninstalls the service by removing information about it from the registry.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the context information associated with the installation. </param>
/// <exception cref="T:System.ComponentModel.Win32Exception">The Service Control Manager could not be opened.-or- The system could not get a handle to the service. </exception>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" />
/// <IPermission class="System.ServiceProcess.ServiceControllerPermission, System.ServiceProcess, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" version="1" Unrestricted="true" />
/// </PermissionSet>
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
this.RemoveService();
}
private static bool ValidateServiceName(string name)
{
if (name != null && name.Length != 0 && name.Length <= 80)
{
char[] array = name.ToCharArray();
for (int i = 0; i < array.Length; i++)
{
if (array[i] < ' ' || array[i] == '/' || array[i] == '\\')
{
return false;
}
}
return true;
}
return false;
}
}
}

@ -1,375 +0,0 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
namespace ZeroLevel.Services.AsService
{
public class ServiceProcessInstaller
: ComponentInstaller
{
private ServiceAccount serviceAccount = ServiceAccount.User;
private bool haveLoginInfo;
private string password;
private string username;
private static bool helpPrinted;
/// <summary>Gets help text displayed for service installation options.</summary>
/// <returns>Help text that provides a description of the steps for setting the user name and password in order to run the service under a particular account.</returns>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
/// </PermissionSet>
public override string HelpText
{
get
{
if (ServiceProcessInstaller.helpPrinted)
{
return base.HelpText;
}
ServiceProcessInstaller.helpPrinted = true;
return Res.GetString("HelpText") + "\r\n" + base.HelpText;
}
}
/// <summary>Gets or sets the password associated with the user account under which the service application runs.</summary>
/// <returns>The password associated with the account under which the service should run. The default is an empty string (""). The property is not public, and is never serialized.</returns>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
/// <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
[Browsable(false)]
public string Password
{
get
{
if (!this.haveLoginInfo)
{
this.GetLoginInfo();
}
return this.password;
}
set
{
this.haveLoginInfo = false;
this.password = value;
}
}
/// <summary>Gets or sets the type of account under which to run this service application.</summary>
/// <returns>A <see cref="T:System.ServiceProcess.ServiceAccount" /> that defines the type of account under which the system runs this service. The default is User.</returns>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
/// <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
[DefaultValue(ServiceAccount.User)]
[ServiceProcessDescription("ServiceProcessInstallerAccount")]
public ServiceAccount Account
{
get
{
if (!this.haveLoginInfo)
{
this.GetLoginInfo();
}
return this.serviceAccount;
}
set
{
this.haveLoginInfo = false;
this.serviceAccount = value;
}
}
/// <summary>Gets or sets the user account under which the service application will run.</summary>
/// <returns>The account under which the service should run. The default is an empty string ("").</returns>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
/// <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
[TypeConverter("System.Diagnostics.Design.StringValueConverter, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[Browsable(false)]
public string Username
{
get
{
if (!this.haveLoginInfo)
{
this.GetLoginInfo();
}
return this.username;
}
set
{
this.haveLoginInfo = false;
this.username = value;
}
}
private static bool AccountHasRight(IntPtr policyHandle, byte[] accountSid, string rightName)
{
IntPtr intPtr = (IntPtr)0;
int num = 0;
int num2 = NativeMethods.LsaEnumerateAccountRights(policyHandle, accountSid, out intPtr, out num);
switch (num2)
{
case -1073741772:
return false;
default:
throw new Win32Exception(SafeNativeMethods.LsaNtStatusToWinError(num2));
case 0:
{
bool result = false;
try
{
IntPtr intPtr2 = intPtr;
for (int i = 0; i < num; i++)
{
NativeMethods.LSA_UNICODE_STRING_withPointer lSA_UNICODE_STRING_withPointer = new NativeMethods.LSA_UNICODE_STRING_withPointer();
Marshal.PtrToStructure(intPtr2, (object)lSA_UNICODE_STRING_withPointer);
char[] array = new char[lSA_UNICODE_STRING_withPointer.length / 2];
Marshal.Copy(lSA_UNICODE_STRING_withPointer.pwstr, array, 0, array.Length);
if (string.Compare(new string(array, 0, array.Length), rightName, StringComparison.Ordinal) == 0)
{
return true;
}
intPtr2 = (IntPtr)((long)intPtr2 + Marshal.SizeOf(typeof(NativeMethods.LSA_UNICODE_STRING)));
}
return result;
}
finally
{
SafeNativeMethods.LsaFreeMemory(intPtr);
}
}
}
}
/// <summary>Implements the base class <see cref="M:System.Configuration.Install.ComponentInstaller.CopyFromComponent(System.ComponentModel.IComponent)" /> method with no <see cref="T:System.ServiceProcess.ServiceProcessInstaller" /> class-specific behavior.</summary>
/// <param name="comp">The <see cref="T:System.ComponentModel.IComponent" /> that represents the service process. </param>
public override void CopyFromComponent(IComponent comp)
{
}
private byte[] GetAccountSid(string accountName)
{
byte[] array = new byte[256];
int[] array2 = new int[1]
{
array.Length
};
char[] array3 = new char[1024];
int[] domNameLen = new int[1]
{
array3.Length
};
int[] sidNameUse = new int[1];
if (accountName.Substring(0, 2) == ".\\")
{
StringBuilder stringBuilder = new StringBuilder(32);
int num = 32;
if (!NativeMethods.GetComputerName(stringBuilder, ref num))
{
throw new Win32Exception();
}
accountName = stringBuilder + accountName.Substring(1);
}
if (!NativeMethods.LookupAccountName(null, accountName, array, array2, array3, domNameLen, sidNameUse))
{
throw new Win32Exception();
}
byte[] array4 = new byte[array2[0]];
Array.Copy(array, 0, array4, 0, array2[0]);
return array4;
}
private void GetLoginInfo()
{
if (base.Context != null && !base.DesignMode && !this.haveLoginInfo)
{
this.haveLoginInfo = true;
if (this.serviceAccount != ServiceAccount.User)
{
return;
}
if (base.Context.Parameters.ContainsKey("username"))
{
this.username = base.Context.Parameters["username"];
}
if (base.Context.Parameters.ContainsKey("password"))
{
this.password = base.Context.Parameters["password"];
}
if (this.username != null && this.username.Length != 0 && this.password != null)
{
return;
}
if (!base.Context.Parameters.ContainsKey("unattended"))
{
throw new PlatformNotSupportedException();
}
throw new InvalidOperationException(Res.GetString("UnattendedCannotPrompt", base.Context.Parameters["assemblypath"]));
}
}
private static void GrantAccountRight(IntPtr policyHandle, byte[] accountSid, string rightName)
{
NativeMethods.LSA_UNICODE_STRING lSA_UNICODE_STRING = new NativeMethods.LSA_UNICODE_STRING();
lSA_UNICODE_STRING.buffer = rightName;
NativeMethods.LSA_UNICODE_STRING lSA_UNICODE_STRING2 = lSA_UNICODE_STRING;
lSA_UNICODE_STRING2.length = (short)(lSA_UNICODE_STRING2.buffer.Length * 2);
NativeMethods.LSA_UNICODE_STRING lSA_UNICODE_STRING3 = lSA_UNICODE_STRING;
lSA_UNICODE_STRING3.maximumLength = lSA_UNICODE_STRING3.length;
int num = NativeMethods.LsaAddAccountRights(policyHandle, accountSid, lSA_UNICODE_STRING, 1);
if (num == 0)
{
return;
}
throw new Win32Exception(SafeNativeMethods.LsaNtStatusToWinError(num));
}
/// <summary>Writes service application information to the registry. This method is meant to be used by installation tools, which call the appropriate methods automatically.</summary>
/// <param name="stateSaver">An <see cref="T:System.Collections.IDictionary" /> that contains the context information associated with the installation. </param>
/// <exception cref="T:System.ArgumentException">The <paramref name="stateSaver" /> is null. </exception>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" />
/// <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
public override void Install(IDictionary stateSaver)
{
try
{
ServiceInstaller.CheckEnvironment();
try
{
if (!this.haveLoginInfo)
{
try
{
this.GetLoginInfo();
}
catch
{
stateSaver["hadServiceLogonRight"] = true;
throw;
}
}
}
finally
{
stateSaver["Account"] = this.Account;
if (this.Account == ServiceAccount.User)
{
stateSaver["Username"] = this.Username;
}
}
if (this.Account == ServiceAccount.User)
{
IntPtr intPtr = this.OpenSecurityPolicy();
bool flag = true;
try
{
byte[] accountSid = this.GetAccountSid(this.Username);
flag = ServiceProcessInstaller.AccountHasRight(intPtr, accountSid, "SeServiceLogonRight");
if (!flag)
{
ServiceProcessInstaller.GrantAccountRight(intPtr, accountSid, "SeServiceLogonRight");
}
}
finally
{
stateSaver["hadServiceLogonRight"] = flag;
SafeNativeMethods.LsaClose(intPtr);
}
}
}
finally
{
base.Install(stateSaver);
}
}
private IntPtr OpenSecurityPolicy()
{
GCHandle gCHandle = GCHandle.Alloc(new NativeMethods.LSA_OBJECT_ATTRIBUTES(), GCHandleType.Pinned);
try
{
int num = 0;
IntPtr pointerObjectAttributes = gCHandle.AddrOfPinnedObject();
IntPtr result = default(IntPtr);
num = NativeMethods.LsaOpenPolicy((NativeMethods.LSA_UNICODE_STRING)null, pointerObjectAttributes, 2064, out result);
if (num != 0)
{
throw new Win32Exception(SafeNativeMethods.LsaNtStatusToWinError(num));
}
return result;
}
finally
{
gCHandle.Free();
}
}
private static void RemoveAccountRight(IntPtr policyHandle, byte[] accountSid, string rightName)
{
NativeMethods.LSA_UNICODE_STRING lSA_UNICODE_STRING = new NativeMethods.LSA_UNICODE_STRING();
lSA_UNICODE_STRING.buffer = rightName;
NativeMethods.LSA_UNICODE_STRING lSA_UNICODE_STRING2 = lSA_UNICODE_STRING;
lSA_UNICODE_STRING2.length = (short)(lSA_UNICODE_STRING2.buffer.Length * 2);
NativeMethods.LSA_UNICODE_STRING lSA_UNICODE_STRING3 = lSA_UNICODE_STRING;
lSA_UNICODE_STRING3.maximumLength = lSA_UNICODE_STRING3.length;
int num = NativeMethods.LsaRemoveAccountRights(policyHandle, accountSid, false, lSA_UNICODE_STRING, 1);
if (num == 0)
{
return;
}
throw new Win32Exception(SafeNativeMethods.LsaNtStatusToWinError(num));
}
/// <summary>Rolls back service application information written to the registry by the installation procedure. This method is meant to be used by installation tools, which process the appropriate methods automatically.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the context information associated with the installation. </param>
/// <exception cref="T:System.ArgumentException">The <paramref name="savedState" /> is null.-or- The <paramref name="savedState" /> is corrupted or non-existent. </exception>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" />
/// </PermissionSet>
public override void Rollback(IDictionary savedState)
{
try
{
if ((ServiceAccount)savedState["Account"] == ServiceAccount.User && !(bool)savedState["hadServiceLogonRight"])
{
string accountName = (string)savedState["Username"];
IntPtr intPtr = this.OpenSecurityPolicy();
try
{
byte[] accountSid = this.GetAccountSid(accountName);
ServiceProcessInstaller.RemoveAccountRight(intPtr, accountSid, "SeServiceLogonRight");
}
finally
{
SafeNativeMethods.LsaClose(intPtr);
}
}
}
finally
{
base.Rollback(savedState);
}
}
}
}

@ -1,76 +0,0 @@
using System;
using System.Collections;
namespace ZeroLevel.Services.AsService
{
public class TransactedInstaller
: Installer
{
public override void Install(IDictionary savedState)
{
if (base.Context == null)
{
base.Context = new InstallContext();
}
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoTransacted"));
try
{
bool flag = true;
try
{
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoBeginInstall"));
base.Install(savedState);
}
catch (Exception ex)
{
flag = false;
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoException"));
Installer.LogException(ex, base.Context);
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoBeginRollback"));
try
{
this.Rollback(savedState);
}
catch (Exception)
{
}
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoRollbackDone"));
throw new InvalidOperationException(Res.GetString("InstallRollback"), ex);
}
if (flag)
{
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoBeginCommit"));
try
{
this.Commit(savedState);
}
finally
{
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoCommitDone"));
}
}
}
finally
{
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoTransactedDone"));
}
}
public override void Uninstall(IDictionary savedState)
{
if (base.Context == null)
{
base.Context = new InstallContext();
}
base.Context.LogMessage(Environment.NewLine + Environment.NewLine + Res.GetString("InstallInfoBeginUninstall"));
try
{
base.Uninstall(savedState);
}
finally
{
base.Context.LogMessage(Environment.NewLine + Res.GetString("InstallInfoUninstallDone"));
}
}
}
}

@ -1,53 +0,0 @@
namespace ZeroLevel.Services.AsService
{
public enum PowerEventCode
{
/// <summary>
/// The system has requested permission to suspend the computer. An application that grants permission should carry out preparations for the suspension before returning.
/// <remarks>Not supported by <see cref="ConsoleRunHost"/></remarks>
/// </summary>
QuerySuspend = 0,
/// <summary>
/// The system was denied permission to suspend the computer. This status is broadcast if any application or driver denied a previous <see cref="QuerySuspend"/> status.
/// <remarks>Not supported by <see cref="ConsoleRunHost"/></remarks>
/// </summary>
QuerySuspendFailed = 2,
/// <summary>
/// The computer is about to enter a suspended state. This event is typically broadcast when all applications and installable drivers have returned true to a previous QuerySuspend state.
/// </summary>
Suspend = 4,
/// <summary>
/// The system has resumed operation after a critical suspension caused by a failing battery.
/// <remarks>Not supported by <see cref="ConsoleRunHost"/></remarks>
/// </summary>
ResumeCritical = 6,
/// <summary>
/// The system has resumed operation after being suspended.
/// <remarks>Not supported by <see cref="ConsoleRunHost"/></remarks>
/// </summary>
ResumeSuspend = 7,
/// <summary>
/// Battery power is low.
/// <remarks>Not supported by <see cref="ConsoleRunHost"/></remarks>
/// </summary>
BatteryLow = 9,
/// <summary>
/// A change in the power status of the computer is detected, such as a switch from battery power to A/C. The system also broadcasts this event when remaining battery power slips below the threshold specified by the user or if the battery power changes by a specified percentage.
/// </summary>
PowerStatusChange = 10,
/// <summary>
/// An Advanced Power Management (APM) BIOS signaled an APM OEM event.
/// <remarks>Not supported by <see cref="ConsoleRunHost"/></remarks>
/// </summary>
OemEvent = 11,
/// <summary>
/// The computer has woken up automatically to handle an event.
/// </summary>
ResumeAutomatic = 18
}
public interface PowerEventArguments
{
PowerEventCode EventCode { get; }
}
}

@ -1,287 +0,0 @@
using System.Globalization;
using System.Resources;
using System.Threading;
namespace ZeroLevel.Services.AsService
{
internal sealed class Res
{
internal const string RTL = "RTL";
internal const string FileName = "FileName";
internal const string ServiceStartedIncorrectly = "ServiceStartedIncorrectly";
internal const string CallbackHandler = "CallbackHandler";
internal const string OpenService = "OpenService";
internal const string StartService = "StartService";
internal const string StopService = "StopService";
internal const string PauseService = "PauseService";
internal const string ResumeService = "ResumeService";
internal const string ControlService = "ControlService";
internal const string ServiceName = "ServiceName";
internal const string ServiceStartType = "ServiceStartType";
internal const string ServiceDependency = "ServiceDependency";
internal const string InstallService = "InstallService";
internal const string InstallError = "InstallError";
internal const string UserName = "UserName";
internal const string UserPassword = "UserPassword";
internal const string ButtonOK = "ButtonOK";
internal const string ServiceUsage = "ServiceUsage";
internal const string ServiceNameTooLongForNt4 = "ServiceNameTooLongForNt4";
internal const string DisplayNameTooLong = "DisplayNameTooLong";
internal const string NoService = "NoService";
internal const string NoDisplayName = "NoDisplayName";
internal const string OpenSC = "OpenSC";
internal const string Timeout = "Timeout";
internal const string CannotChangeProperties = "CannotChangeProperties";
internal const string CannotChangeName = "CannotChangeName";
internal const string NoServices = "NoServices";
internal const string NoMachineName = "NoMachineName";
internal const string BadMachineName = "BadMachineName";
internal const string NoGivenName = "NoGivenName";
internal const string CannotStart = "CannotStart";
internal const string NotAService = "NotAService";
internal const string NoInstaller = "NoInstaller";
internal const string UserCanceledInstall = "UserCanceledInstall";
internal const string UnattendedCannotPrompt = "UnattendedCannotPrompt";
internal const string InvalidParameter = "InvalidParameter";
internal const string FailedToUnloadAppDomain = "FailedToUnloadAppDomain";
internal const string NotInPendingState = "NotInPendingState";
internal const string ArgsCantBeNull = "ArgsCantBeNull";
internal const string StartSuccessful = "StartSuccessful";
internal const string StopSuccessful = "StopSuccessful";
internal const string PauseSuccessful = "PauseSuccessful";
internal const string ContinueSuccessful = "ContinueSuccessful";
internal const string InstallSuccessful = "InstallSuccessful";
internal const string UninstallSuccessful = "UninstallSuccessful";
internal const string CommandSuccessful = "CommandSuccessful";
internal const string StartFailed = "StartFailed";
internal const string StopFailed = "StopFailed";
internal const string PauseFailed = "PauseFailed";
internal const string ContinueFailed = "ContinueFailed";
internal const string SessionChangeFailed = "SessionChangeFailed";
internal const string InstallFailed = "InstallFailed";
internal const string UninstallFailed = "UninstallFailed";
internal const string CommandFailed = "CommandFailed";
internal const string ErrorNumber = "ErrorNumber";
internal const string ShutdownOK = "ShutdownOK";
internal const string ShutdownFailed = "ShutdownFailed";
internal const string PowerEventOK = "PowerEventOK";
internal const string PowerEventFailed = "PowerEventFailed";
internal const string InstallOK = "InstallOK";
internal const string TryToStop = "TryToStop";
internal const string ServiceRemoving = "ServiceRemoving";
internal const string ServiceRemoved = "ServiceRemoved";
internal const string HelpText = "HelpText";
internal const string CantStartFromCommandLine = "CantStartFromCommandLine";
internal const string CantStartFromCommandLineTitle = "CantStartFromCommandLineTitle";
internal const string CantRunOnWin9x = "CantRunOnWin9x";
internal const string CantRunOnWin9xTitle = "CantRunOnWin9xTitle";
internal const string CantControlOnWin9x = "CantControlOnWin9x";
internal const string CantInstallOnWin9x = "CantInstallOnWin9x";
internal const string InstallingService = "InstallingService";
internal const string StartingService = "StartingService";
internal const string SBAutoLog = "SBAutoLog";
internal const string SBServiceName = "SBServiceName";
internal const string SBServiceDescription = "SBServiceDescription";
internal const string ServiceControllerDesc = "ServiceControllerDesc";
internal const string SPCanPauseAndContinue = "SPCanPauseAndContinue";
internal const string SPCanShutdown = "SPCanShutdown";
internal const string SPCanStop = "SPCanStop";
internal const string SPDisplayName = "SPDisplayName";
internal const string SPDependentServices = "SPDependentServices";
internal const string SPMachineName = "SPMachineName";
internal const string SPServiceName = "SPServiceName";
internal const string SPServicesDependedOn = "SPServicesDependedOn";
internal const string SPStatus = "SPStatus";
internal const string SPServiceType = "SPServiceType";
internal const string SPStartType = "SPStartType";
internal const string ServiceProcessInstallerAccount = "ServiceProcessInstallerAccount";
internal const string ServiceInstallerDescription = "ServiceInstallerDescription";
internal const string ServiceInstallerServicesDependedOn = "ServiceInstallerServicesDependedOn";
internal const string ServiceInstallerServiceName = "ServiceInstallerServiceName";
internal const string ServiceInstallerStartType = "ServiceInstallerStartType";
internal const string ServiceInstallerDelayedAutoStart = "ServiceInstallerDelayedAutoStart";
internal const string ServiceInstallerDisplayName = "ServiceInstallerDisplayName";
internal const string Label_SetServiceLogin = "Label_SetServiceLogin";
internal const string Label_MissmatchedPasswords = "Label_MissmatchedPasswords";
private static Res loader;
private ResourceManager resources;
private static CultureInfo Culture
{
get
{
return null;
}
}
public static ResourceManager Resources
{
get
{
return Res.GetLoader().resources;
}
}
internal Res()
{
this.resources = new ResourceManager("System.ServiceProcess", base.GetType().Assembly);
}
private static Res GetLoader()
{
if (Res.loader == null)
{
Res value = new Res();
Interlocked.CompareExchange<Res>(ref Res.loader, value, (Res)null);
}
return Res.loader;
}
public static string GetString(string name, params object[] args)
{
Res res = Res.GetLoader();
if (res == null)
{
return null;
}
string @string = res.resources.GetString(name, Res.Culture);
if (args != null && args.Length != 0)
{
for (int i = 0; i < args.Length; i++)
{
string text = args[i] as string;
if (text != null && text.Length > 1024)
{
args[i] = text.Substring(0, 1021) + "...";
}
}
return string.Format(CultureInfo.CurrentCulture, @string, args);
}
return @string;
}
public static string GetString(string name)
{
Res res = Res.GetLoader();
if (res == null)
{
return null;
}
return res.resources.GetString(name, Res.Culture);
}
public static string GetString(string name, out bool usedFallback)
{
usedFallback = false;
return Res.GetString(name);
}
public static object GetObject(string name)
{
Res res = Res.GetLoader();
if (res == null)
{
return null;
}
return res.resources.GetObject(name, Res.Culture);
}
}
}

@ -1,29 +0,0 @@
using System;
using System.ComponentModel;
namespace ZeroLevel.Services.AsService
{
[AttributeUsage(AttributeTargets.All)]
internal sealed class ResDescriptionAttribute : DescriptionAttribute
{
private bool replaced;
public override string Description
{
get
{
if (!this.replaced)
{
this.replaced = true;
base.DescriptionValue = Res.GetString(base.Description);
}
return base.Description;
}
}
public ResDescriptionAttribute(string description)
: base(description)
{
}
}
}

@ -1,28 +0,0 @@
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
namespace ZeroLevel.Services.AsService
{
[SuppressUnmanagedCodeSecurity]
public partial class SafeNativeMethods
{
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static extern bool CloseServiceHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
public static extern int LsaClose(IntPtr objectHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
public static extern int LsaNtStatusToWinError(int ntStatus);
[DllImport("advapi32.dll")]
public static extern int LsaFreeMemory(IntPtr ptr);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, int access);
}
}

@ -1,14 +0,0 @@
namespace ZeroLevel.Services.AsService
{
public enum ServiceAccount
{
/// <summary>An account that acts as a non-privileged user on the local computer, and presents anonymous credentials to any remote server.</summary>
LocalService,
/// <summary>An account that provides extensive local privileges, and presents the computer's credentials to any remote server.</summary>
NetworkService,
/// <summary>An account, used by the service control manager, that has extensive privileges on the local computer and acts as the computer on the network.</summary>
LocalSystem,
/// <summary>An account defined by a specific user on the network. Specifying User for the <see cref="P:System.ServiceProcess.ServiceProcessInstaller.Account" /> member causes the system to prompt for a valid user name and password when the service is installed, unless you set values for both the <see cref="P:System.ServiceProcess.ServiceProcessInstaller.Username" /> and <see cref="P:System.ServiceProcess.ServiceProcessInstaller.Password" /> properties of your <see cref="T:System.ServiceProcess.ServiceProcessInstaller" /> instance.</summary>
User
}
}

@ -1,40 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace ZeroLevel.Services.AsService
{
[Serializable]
public class ServiceControlException :
Exception
{
public ServiceControlException()
{
}
public ServiceControlException(string message)
: base(message)
{
}
public ServiceControlException(string message, Exception innerException)
: base(message, innerException)
{
}
protected ServiceControlException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public ServiceControlException(string format, Type serviceType, string command, Exception innerException)
: this(FormatMessage(format, serviceType, command), innerException)
{
}
static string FormatMessage(string format, Type serviceType, string command)
{
return string.Format(format, serviceType, command);
}
}
}

@ -1,16 +0,0 @@
namespace ZeroLevel.Services.AsService
{
public static class ServiceControllerExtensions
{
public static bool ValidServiceName(string serviceName)
{
if (serviceName != null
&& serviceName.Length <= 80
&& serviceName.Length != 0)
{
return serviceName.IndexOfAny(new[] { '\\', '/' }) == -1;
}
return false;
}
}
}

@ -1,66 +0,0 @@
using System;
namespace ZeroLevel.Services.AsService
{
/// <summary>
/// A handle to a service being hosted by the Host
/// </summary>
public interface ServiceHandle :
IDisposable
{
/// <summary>
/// Start the service
/// </summary>
/// <param name="hostControl"></param>
/// <returns>True if the service was started, otherwise false</returns>
bool Start(HostControl hostControl);
/// <summary>
/// Pause the service
/// </summary>
/// <param name="hostControl"></param>
/// <returns>True if the service was paused, otherwise false</returns>
bool Pause(HostControl hostControl);
/// <summary>
/// Continue the service from a paused state
/// </summary>
/// <param name="hostControl"></param>
/// <returns>True if the service was able to continue, otherwise false</returns>
bool Continue(HostControl hostControl);
/// <summary>
/// Stop the service
/// </summary>
/// <param name="hostControl"></param>
/// <returns>True if the service was stopped, or false if the service cannot be stopped at this time</returns>
bool Stop(HostControl hostControl);
/// <summary>
/// Handle the shutdown event
/// </summary>
/// <param name="hostControl"></param>
void Shutdown(HostControl hostControl);
/// <summary>
/// Handle the session change event
/// </summary>
/// <param name="hostControl"></param>
/// <param name="arguments"></param>
void SessionChanged(HostControl hostControl, SessionChangedArguments arguments);
/// <summary>
/// Handle the power change event
/// </summary>
/// <param name="hostControl"></param>
/// <param name="arguments"></param>
bool PowerEvent(HostControl hostControl, PowerEventArguments arguments);
/// <summary>
/// Handle the custom command
/// </summary>
/// <param name="hostControl"></param>
/// <param name="command"></param>
void CustomCommand(HostControl hostControl, int command);
}
}

@ -1,21 +0,0 @@
namespace ZeroLevel.Services.AsService
{
public enum SessionChangeReasonCode
{
ConsoleConnect = 1,
ConsoleDisconnect = 2,
RemoteConnect = 3,
RemoteDisconnect = 4,
SessionLogon = 5,
SessionLogoff = 6,
SessionLock = 7,
SessionUnlock = 8,
SessionRemoteControl = 9,
}
public interface SessionChangedArguments
{
SessionChangeReasonCode ReasonCode { get; }
int SessionId { get; }
}
}

@ -1,276 +0,0 @@
using Microsoft.Win32;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;
using ZeroLevel.Services.AsService;
namespace System.Diagnostics
{
public class EventLogInstaller
: ComponentInstaller
{
private EventSourceCreationData sourceData = new EventSourceCreationData(null, null);
private UninstallAction uninstallAction;
/// <summary>Gets or sets the path of the resource file that contains category strings for the source.</summary>
/// <returns>The path of the category resource file. The default is an empty string ("").</returns>
[TypeConverter("System.Diagnostics.Design.StringValueConverter, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[Editor("System.Windows.Forms.Design.FileNameEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[ComVisible(false)]
[ResDescription("Desc_CategoryResourceFile")]
public string CategoryResourceFile
{
get
{
return this.sourceData.CategoryResourceFile;
}
set
{
this.sourceData.CategoryResourceFile = value;
}
}
/// <summary>Gets or sets the number of categories in the category resource file.</summary>
/// <returns>The number of categories in the category resource file. The default value is zero.</returns>
[ComVisible(false)]
[ResDescription("Desc_CategoryCount")]
public int CategoryCount
{
get
{
return this.sourceData.CategoryCount;
}
set
{
this.sourceData.CategoryCount = value;
}
}
/// <summary>Gets or sets the name of the log to set the source to.</summary>
/// <returns>The name of the log. This can be Application, System, or a custom log name. The default is an empty string ("").</returns>
[TypeConverter("System.Diagnostics.Design.StringValueConverter, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[ResDescription("Desc_Log")]
public string Log
{
get
{
if (this.sourceData.LogName == null && this.sourceData.Source != null)
{
this.sourceData.LogName = EventLog.LogNameFromSourceName(this.sourceData.Source, ".");
}
return this.sourceData.LogName;
}
set
{
this.sourceData.LogName = value;
}
}
/// <summary>Gets or sets the path of the resource file that contains message formatting strings for the source.</summary>
/// <returns>The path of the message resource file. The default is an empty string ("").</returns>
[TypeConverter("System.Diagnostics.Design.StringValueConverter, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[Editor("System.Windows.Forms.Design.FileNameEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[ComVisible(false)]
[ResDescription("Desc_MessageResourceFile")]
public string MessageResourceFile
{
get
{
return this.sourceData.MessageResourceFile;
}
set
{
this.sourceData.MessageResourceFile = value;
}
}
/// <summary>Gets or sets the path of the resource file that contains message parameter strings for the source.</summary>
/// <returns>The path of the message parameter resource file. The default is an empty string ("").</returns>
[TypeConverter("System.Diagnostics.Design.StringValueConverter, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[Editor("System.Windows.Forms.Design.FileNameEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[ComVisible(false)]
[ResDescription("Desc_ParameterResourceFile")]
public string ParameterResourceFile
{
get
{
return this.sourceData.ParameterResourceFile;
}
set
{
this.sourceData.ParameterResourceFile = value;
}
}
/// <summary>Gets or sets the source name to register with the log.</summary>
/// <returns>The name to register with the event log as a source of entries. The default is an empty string ("").</returns>
[TypeConverter("System.Diagnostics.Design.StringValueConverter, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[ResDescription("Desc_Source")]
public string Source
{
get
{
return this.sourceData.Source;
}
set
{
this.sourceData.Source = value;
}
}
/// <summary>Gets or sets a value that indicates whether the Installutil.exe (Installer Tool) should remove the event log or leave it in its installed state at uninstall time.</summary>
/// <returns>One of the <see cref="T:System.Configuration.Install.UninstallAction" /> values that indicates what state to leave the event log in when the <see cref="T:System.Diagnostics.EventLog" /> is uninstalled. The default is Remove.</returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">
/// <see cref="P:System.Diagnostics.EventLogInstaller.UninstallAction" /> contains an invalid value. The only valid values for this property are Remove and NoAction.</exception>
[DefaultValue(UninstallAction.Remove)]
[ResDescription("Desc_UninstallAction")]
public UninstallAction UninstallAction
{
get
{
return this.uninstallAction;
}
set
{
if (!Enum.IsDefined(typeof(UninstallAction), value))
{
throw new InvalidEnumArgumentException("value", (int)value, typeof(UninstallAction));
}
this.uninstallAction = value;
}
}
/// <summary>Copies the property values of an <see cref="T:System.Diagnostics.EventLog" /> component that are required at installation time for an event log.</summary>
/// <param name="component">An <see cref="T:System.ComponentModel.IComponent" /> to use as a template for the <see cref="T:System.Diagnostics.EventLogInstaller" />. </param>
/// <exception cref="T:System.ArgumentException">The specified component is not an <see cref="T:System.Diagnostics.EventLog" />.-or- The <see cref="P:System.Diagnostics.EventLog.Log" /> or <see cref="P:System.Diagnostics.EventLog.Source" /> property of the specified component is either null or empty. </exception>
public override void CopyFromComponent(IComponent component)
{
EventLog eventLog = component as EventLog;
if (eventLog == null)
{
throw new ArgumentException(Res.GetString("NotAnEventLog"));
}
if (eventLog.Log != null && !(eventLog.Log == string.Empty) && eventLog.Source != null && !(eventLog.Source == string.Empty))
{
this.Log = eventLog.Log;
this.Source = eventLog.Source;
return;
}
throw new ArgumentException(Res.GetString("IncompleteEventLog"));
}
/// <summary>Performs the installation and writes event log information to the registry.</summary>
/// <param name="stateSaver">An <see cref="T:System.Collections.IDictionary" /> used to save information needed to perform a rollback or uninstall operation. </param>
/// <exception cref="T:System.PlatformNotSupportedException">The platform the installer is trying to use is not Windows NT 4.0 or later. </exception>
/// <exception cref="T:System.ArgumentException">The name specified in the <see cref="P:System.Diagnostics.EventLogInstaller.Source" /> property is already registered for a different event log.</exception>
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
base.Context.LogMessage(Res.GetString("CreatingEventLog", this.Source, this.Log));
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
throw new PlatformNotSupportedException(Res.GetString("WinNTRequired"));
}
stateSaver["baseInstalledAndPlatformOK"] = true;
bool flag = EventLog.Exists(this.Log, ".");
stateSaver["logExists"] = flag;
bool flag2 = EventLog.SourceExists(this.Source, ".");
stateSaver["alreadyRegistered"] = flag2;
if (flag2 && EventLog.LogNameFromSourceName(this.Source, ".") == this.Log)
{
return;
}
EventLog.CreateEventSource(this.sourceData);
}
/// <summary>Determines whether an installer and another specified installer refer to the same source.</summary>
/// <returns>true if this installer and the installer specified by the <paramref name="otherInstaller" /> parameter would install or uninstall the same source; otherwise, false.</returns>
/// <param name="otherInstaller">The installer to compare. </param>
public override bool IsEquivalentInstaller(ComponentInstaller otherInstaller)
{
EventLogInstaller eventLogInstaller = otherInstaller as EventLogInstaller;
if (eventLogInstaller == null)
{
return false;
}
return eventLogInstaller.Source == this.Source;
}
/// <summary>Restores the computer to the state it was in before the installation by rolling back the event log information that the installation procedure wrote to the registry.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the pre-installation state of the computer. </param>
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
base.Context.LogMessage(Res.GetString("RestoringEventLog", this.Source));
if (savedState["baseInstalledAndPlatformOK"] != null)
{
if (!(bool)savedState["logExists"])
{
EventLog.Delete(this.Log, ".");
}
else
{
object obj = savedState["alreadyRegistered"];
bool flag = obj != null && (bool)obj;
if (!flag && EventLog.SourceExists(this.Source, "."))
{
EventLog.DeleteEventSource(this.Source, ".");
}
}
}
}
/// <summary>Removes an installation by removing event log information from the registry.</summary>
/// <param name="savedState">An <see cref="T:System.Collections.IDictionary" /> that contains the pre-installation state of the computer. </param>
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
if (this.UninstallAction == UninstallAction.Remove)
{
base.Context.LogMessage(Res.GetString("RemovingEventLog", this.Source));
if (EventLog.SourceExists(this.Source, "."))
{
if (string.Compare(this.Log, this.Source, StringComparison.OrdinalIgnoreCase) != 0)
{
EventLog.DeleteEventSource(this.Source, ".");
}
}
else
{
base.Context.LogMessage(Res.GetString("LocalSourceNotRegisteredWarning", this.Source));
}
RegistryKey registryKey = Registry.LocalMachine;
RegistryKey registryKey2 = null;
try
{
registryKey = registryKey.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\EventLog", false);
if (registryKey != null)
{
registryKey2 = registryKey.OpenSubKey(this.Log, false);
}
if (registryKey2 != null)
{
string[] subKeyNames = registryKey2.GetSubKeyNames();
if (subKeyNames == null || subKeyNames.Length == 0 || (subKeyNames.Length == 1 && string.Compare(subKeyNames[0], this.Log, StringComparison.OrdinalIgnoreCase) == 0))
{
base.Context.LogMessage(Res.GetString("DeletingEventLog", this.Log));
EventLog.Delete(this.Log, ".");
}
}
}
finally
{
if (registryKey != null)
{
registryKey.Close();
}
if (registryKey2 != null)
{
registryKey2.Close();
}
}
}
}
}
}

@ -1,11 +0,0 @@
namespace System.Diagnostics
{
/// <summary>Specifies what an installer should do during an uninstallation.</summary>
public enum UninstallAction
{
/// <summary>Removes the resource the installer created.</summary>
Remove,
/// <summary>Leaves the resource created by the installer as is.</summary>
NoAction
}
}

@ -1,56 +0,0 @@
using Microsoft.Win32;
using System.Collections;
namespace ZeroLevel.Services.AsService
{
public class HostInstaller :
Installer
{
readonly string _arguments;
readonly Installer[] _installers;
readonly HostSettings _settings;
public HostInstaller(HostSettings settings, string arguments, Installer[] installers)
{
_installers = installers;
_arguments = arguments;
_settings = settings;
}
public override void Install(IDictionary stateSaver)
{
Installers.AddRange(_installers);
Log.Info("Installing {0} service", _settings.DisplayName);
base.Install(stateSaver);
Log.Debug("Open Registry");
using (RegistryKey system = Registry.LocalMachine.OpenSubKey("System"))
using (RegistryKey currentControlSet = system.OpenSubKey("CurrentControlSet"))
using (RegistryKey services = currentControlSet.OpenSubKey("Services"))
using (RegistryKey service = services.OpenSubKey(_settings.ServiceName, true))
{
service.SetValue("Description", _settings.Description);
var imagePath = (string)service.GetValue("ImagePath");
Log.Debug("Service path: {0}", imagePath);
imagePath += _arguments;
Log.Debug("Image path: {0}", imagePath);
service.SetValue("ImagePath", imagePath);
}
Log.Debug("Closing Registry");
}
public override void Uninstall(IDictionary savedState)
{
Installers.AddRange(_installers);
Log.Info("Uninstalling {0} service", _settings.Name);
base.Uninstall(savedState);
}
}
}

@ -1,224 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;
using System.Text;
namespace ZeroLevel.Services.AsService
{
public class HostServiceInstaller :
IDisposable
{
readonly Installer _installer;
readonly TransactedInstaller _transactedInstaller;
public ServiceProcessInstaller ServiceProcessInstaller
{
get
{
return (ServiceProcessInstaller)_installer.Installers[1];
}
}
public HostServiceInstaller(InstallHostSettings settings)
{
_installer = CreateInstaller(settings);
_transactedInstaller = CreateTransactedInstaller(_installer);
}
public HostServiceInstaller(HostSettings settings)
{
_installer = CreateInstaller(settings);
_transactedInstaller = CreateTransactedInstaller(_installer);
}
public void Dispose()
{
try
{
_transactedInstaller.Dispose();
}
finally
{
_installer.Dispose();
}
}
public void InstallService(Action<InstallEventArgs> beforeInstall, Action<InstallEventArgs> afterInstall, Action<InstallEventArgs> beforeRollback, Action<InstallEventArgs> afterRollback)
{
if (beforeInstall != null)
_installer.BeforeInstall += (sender, args) => beforeInstall(args);
if (afterInstall != null)
_installer.AfterInstall += (sender, args) => afterInstall(args);
if (beforeRollback != null)
_installer.BeforeRollback += (sender, args) => beforeRollback(args);
if (afterRollback != null)
_installer.AfterRollback += (sender, args) => afterRollback(args);
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
_transactedInstaller.Install(new Hashtable());
}
public void UninstallService(Action<InstallEventArgs> beforeUninstall, Action<InstallEventArgs> afterUninstall)
{
if (beforeUninstall != null)
_installer.BeforeUninstall += (sender, args) => beforeUninstall(args);
if (afterUninstall != null)
_installer.AfterUninstall += (sender, args) => afterUninstall(args);
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
_transactedInstaller.Uninstall(null);
}
static Installer CreateInstaller(InstallHostSettings settings)
{
var installers = new Installer[]
{
ConfigureServiceInstaller(settings, settings.Dependencies, settings.StartMode),
ConfigureServiceProcessInstaller(settings.Credentials.Account, settings.Credentials.Username, settings.Credentials.Password)
};
//DO not auto create EventLog Source while install service
//MSDN: When the installation is performed, it automatically creates an EventLogInstaller to install the event log source associated with the ServiceBase derived class. The Log property for this source is set by the ServiceInstaller constructor to the computer's Application log. When you set the ServiceName of the ServiceInstaller (which should be identical to the ServiceBase..::.ServiceName of the service), the Source is automatically set to the same value. In an installation failure, the source's installation is rolled-back along with previously installed services.
//MSDN: from EventLog.CreateEventSource Method (String, String) : an ArgumentException thrown when The first 8 characters of logName match the first 8 characters of an existing event log name.
RemoveEventLogInstallers(installers);
return CreateHostInstaller(settings, installers);
}
private static void RemoveEventLogInstallers(Installer[] installers)
{
foreach (var installer in installers)
{
var eventLogInstallers = installer.Installers.OfType<EventLogInstaller>().ToArray();
foreach (var eventLogInstaller in eventLogInstallers)
{
installer.Installers.Remove(eventLogInstaller);
}
}
}
Installer CreateInstaller(HostSettings settings)
{
var installers = new Installer[]
{
ConfigureServiceInstaller(settings, new string[] {}, HostStartMode.Automatic),
ConfigureServiceProcessInstaller(ServiceAccount.LocalService, "", ""),
};
RemoveEventLogInstallers(installers);
return CreateHostInstaller(settings, installers);
}
static Installer CreateHostInstaller(HostSettings settings, Installer[] installers)
{
string arguments = " ";
if (!string.IsNullOrEmpty(settings.InstanceName))
arguments += $" -instance \"{settings.InstanceName}\"";
if (!string.IsNullOrEmpty(settings.DisplayName))
arguments += $" -displayname \"{settings.DisplayName}\"";
if (!string.IsNullOrEmpty(settings.Name))
arguments += $" -servicename \"{settings.Name}\"";
return new HostInstaller(settings, arguments, installers);
}
static TransactedInstaller CreateTransactedInstaller(Installer installer)
{
var transactedInstaller = new TransactedInstaller();
transactedInstaller.Installers.Add(installer);
Assembly assembly = Assembly.GetEntryAssembly();
Process currentProcess = Process.GetCurrentProcess();
if (assembly == null)
throw new Exception("Assembly.GetEntryAssembly() is null for some reason.");
if (currentProcess == null)
throw new Exception("Process.GetCurrentProcess() is null for some reason.");
string path =
IsDotnetExe(currentProcess)
? $"/assemblypath={currentProcess.MainModule.FileName} \"{assembly.Location}\""
: $"/assemblypath={currentProcess.MainModule.FileName}";
string[] commandLine = { path };
var context = new InstallContext(null, commandLine);
transactedInstaller.Context = context;
return transactedInstaller;
}
static bool IsDotnetExe(Process process) =>
process
.MainModule
.ModuleName
.Equals("dotnet.exe", StringComparison.InvariantCultureIgnoreCase);
static ServiceInstaller ConfigureServiceInstaller(HostSettings settings, string[] dependencies,
HostStartMode startMode)
{
var installer = new ServiceInstaller
{
ServiceName = settings.ServiceName,
Description = settings.Description,
DisplayName = settings.DisplayName,
ServicesDependedOn = dependencies
};
SetStartMode(installer, startMode);
return installer;
}
static void SetStartMode(ServiceInstaller installer, HostStartMode startMode)
{
switch (startMode)
{
case HostStartMode.Automatic:
installer.StartType = ServiceStartMode.Automatic;
break;
case HostStartMode.Manual:
installer.StartType = ServiceStartMode.Manual;
break;
case HostStartMode.Disabled:
installer.StartType = ServiceStartMode.Disabled;
break;
case HostStartMode.AutomaticDelayed:
installer.StartType = ServiceStartMode.Automatic;
installer.DelayedAutoStart = true;
break;
}
}
static ServiceProcessInstaller ConfigureServiceProcessInstaller(ServiceAccount account, string username,
string password)
{
var installer = new ServiceProcessInstaller
{
Username = username,
Password = password,
Account = account,
};
return installer;
}
}
}

@ -1,34 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace ZeroLevel.Services.AsService
{
static class Kernel32
{
public static uint TH32CS_SNAPPROCESS = 2;
[StructLayout(LayoutKind.Sequential)]
public struct PROCESSENTRY32
{
public uint dwSize;
public uint cntUsage;
public uint th32ProcessID;
public IntPtr th32DefaultHeapID;
public uint th32ModuleID;
public uint cntThreads;
public uint th32ParentProcessID;
public int pcPriClassBase;
public uint dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szExeFile;
};
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);
[DllImport("kernel32.dll")]
public static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll")]
public static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
}
}

@ -1,91 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace ZeroLevel.Services.AsService
{
public partial class NativeMethods
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class LSA_UNICODE_STRING_withPointer
{
public short length;
public short maximumLength;
public IntPtr pwstr = (IntPtr)0;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class LSA_UNICODE_STRING
{
public short length;
public short maximumLength;
public string buffer;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class LSA_OBJECT_ATTRIBUTES
{
public int length;
public IntPtr rootDirectory = (IntPtr)0;
public IntPtr pointerLsaString = (IntPtr)0;
public int attributes;
public IntPtr pointerSecurityDescriptor = (IntPtr)0;
public IntPtr pointerSecurityQualityOfService = (IntPtr)0;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SERVICE_DELAYED_AUTOSTART_INFO
{
public bool fDelayedAutostart;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SERVICE_DESCRIPTION
{
public IntPtr description;
}
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool ChangeServiceConfig2(IntPtr serviceHandle, uint infoLevel, ref SERVICE_DESCRIPTION serviceDesc);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool ChangeServiceConfig2(IntPtr serviceHandle, uint infoLevel, ref SERVICE_DELAYED_AUTOSTART_INFO serviceDesc);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateService(IntPtr databaseHandle, string serviceName, string displayName, int access, int serviceType, int startType, int errorControl, string binaryPath, string loadOrderGroup, IntPtr pTagId, string dependencies, string servicesStartName, string password);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool LookupAccountName(string systemName, string accountName, byte[] sid, int[] sidLen, char[] refDomainName, int[] domNameLen, [In] [Out] int[] sidNameUse);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
public static extern int LsaAddAccountRights(IntPtr policyHandle, byte[] accountSid, LSA_UNICODE_STRING userRights, int countOfRights);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
public static extern int LsaEnumerateAccountRights(IntPtr policyHandle, byte[] accountSid, out IntPtr pLsaUnicodeStringUserRights, out int RightsCount);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
public static extern int LsaOpenPolicy(LSA_UNICODE_STRING systemName, IntPtr pointerObjectAttributes, int desiredAccess, out IntPtr pointerPolicyHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
public static extern int LsaRemoveAccountRights(IntPtr policyHandle, byte[] accountSid, bool allRights, LSA_UNICODE_STRING userRights, int countOfRights);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool GetComputerName(StringBuilder lpBuffer, ref int nSize);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool DeleteService(IntPtr serviceHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenService(IntPtr databaseHandle, string serviceName, int access);
}
}

@ -1,26 +0,0 @@
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
namespace ZeroLevel.Services.AsService
{
public sealed class SafeTokenHandle
: SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle()
: base(true) { }
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
}

@ -1,352 +0,0 @@
using System;
using System.IO;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;
namespace ZeroLevel.Services.AsService.Windows
{
public class WindowsServiceHost :
ServiceBase,
Host,
HostControl
{
readonly HostConfigurator _configurator;
readonly HostEnvironment _environment;
readonly ServiceHandle _serviceHandle;
readonly HostSettings _settings;
int _deadThread;
bool _disposed;
Exception _unhandledException;
public WindowsServiceHost(HostEnvironment environment, HostSettings settings, ServiceHandle serviceHandle, HostConfigurator configurator)
{
if (settings == null)
throw new ArgumentNullException(nameof(settings));
if (serviceHandle == null)
throw new ArgumentNullException(nameof(serviceHandle));
_settings = settings;
_serviceHandle = serviceHandle;
_environment = environment;
_configurator = configurator;
CanPauseAndContinue = settings.CanPauseAndContinue;
CanShutdown = settings.CanShutdown;
CanHandlePowerEvent = settings.CanHandlePowerEvent;
CanHandleSessionChangeEvent = settings.CanSessionChanged;
ServiceName = _settings.ServiceName;
}
public ExitCode Run()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
AppDomain.CurrentDomain.UnhandledException += CatchUnhandledException;
ExitCode = (int)AsService.ExitCode.Ok;
Log.Info("Starting as a Windows service");
if (!_environment.IsServiceInstalled(_settings.ServiceName))
{
string message = $"The {_settings.ServiceName} service has not been installed yet. Please run '{Assembly.GetEntryAssembly().GetName()} install'.";
Log.Fatal(message);
ExitCode = (int)AsService.ExitCode.ServiceNotInstalled;
throw new Exception(message);
}
Log.Debug("[AsService] Starting up as a windows service application");
Run(this);
return (ExitCode)Enum.ToObject(typeof(ExitCode), ExitCode);
}
void HostControl.RequestAdditionalTime(TimeSpan timeRemaining)
{
Log.Debug("Requesting additional time: {0}", timeRemaining);
RequestAdditionalTime((int)timeRemaining.TotalMilliseconds);
}
void HostControl.Stop()
{
InternalStop();
}
void HostControl.Stop(ExitCode exitCode)
{
InternalStop(exitCode);
}
void InternalStop(ExitCode? exitCode = null)
{
if (CanStop)
{
Log.Debug("Stop requested by hosted service");
if (exitCode.HasValue)
ExitCode = (int)exitCode.Value;
Stop();
}
else
{
Log.Debug("Stop requested by hosted service, but service cannot be stopped at this time");
throw new ServiceControlException("The service cannot be stopped at this time");
}
}
protected override void OnStart(string[] args)
{
try
{
Log.Info("[AsService] Starting");
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Log.Debug("[AsService] Current Directory: {0}", Directory.GetCurrentDirectory());
Log.Debug("[AsService] Arguments: {0}", string.Join(",", args));
string startArgs = string.Join(" ", args);
_configurator.ApplyCommandLine(startArgs);
if (!_serviceHandle.Start(this))
throw new Exception("The service did not start successfully (returned false).");
Log.Info("[AsService] Started");
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
Log.Fatal("The service did not start successfully", ex);
ExitCode = (int)AsService.ExitCode.ServiceControlRequestFailed;
throw;
}
}
protected override void OnStop()
{
try
{
Log.Info("[AsService] Stopping");
if (!_serviceHandle.Stop(this))
throw new Exception("The service did not stop successfully (return false).");
Log.Info("[AsService] Stopped");
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
Log.Fatal("The service did not shut down gracefully", ex);
ExitCode = (int)AsService.ExitCode.ServiceControlRequestFailed;
throw;
}
if (_unhandledException != null)
{
ExitCode = (int)AsService.ExitCode.AbnormalExit;
Log.Info("[AsService] Unhandled exception detected, rethrowing to cause application to restart.");
throw new InvalidOperationException("An unhandled exception was detected", _unhandledException);
}
}
protected override void OnPause()
{
try
{
Log.Info("[AsService] Pausing service");
if (!_serviceHandle.Pause(this))
throw new Exception("The service did not pause successfully (returned false).");
Log.Info("[AsService] Paused");
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
Log.Fatal("The service did not pause gracefully", ex);
throw;
}
}
protected override void OnContinue()
{
try
{
Log.Info("[AsService] Resuming service");
if (!_serviceHandle.Continue(this))
throw new Exception("The service did not continue successfully (returned false).");
Log.Info("[AsService] Resumed");
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
Log.Fatal("The service did not resume successfully", ex);
throw;
}
}
protected override void OnShutdown()
{
try
{
Log.Info("[AsService] Service is being shutdown");
_serviceHandle.Shutdown(this);
Log.Info("[AsService] Stopped");
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
Log.Fatal("The service did not shut down gracefully", ex);
ExitCode = (int)AsService.ExitCode.ServiceControlRequestFailed;
throw;
}
}
protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
try
{
Log.Info("[AsService] Service session changed");
var arguments = new WindowsSessionChangedArguments(changeDescription);
_serviceHandle.SessionChanged(this, arguments);
Log.Info("[AsService] Service session changed handled");
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
Log.Fatal("The did not handle Service session change correctly", ex);
ExitCode = (int)AsService.ExitCode.ServiceControlRequestFailed;
throw;
}
}
protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
{
try
{
Log.Info("[AsService] Power event raised");
var arguments = new WindowsPowerEventArguments(powerStatus);
bool result = _serviceHandle.PowerEvent(this, arguments);
Log.Info("[AsService] Power event handled");
return result;
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
Log.Fatal("The service did handle the Power event correctly", ex);
ExitCode = (int)AsService.ExitCode.ServiceControlRequestFailed;
throw;
}
}
protected override void OnCustomCommand(int command)
{
try
{
Log.Info("[AsService] Custom command {0} received", command);
_serviceHandle.CustomCommand(this, command);
Log.Info("[AsService] Custom command {0} processed", command);
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
Log.Error("Unhandled exception during custom command processing detected", ex);
}
}
protected override void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
_serviceHandle?.Dispose();
_disposed = true;
}
base.Dispose(disposing);
}
void CatchUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
_settings.ExceptionCallback?.Invoke((Exception)e.ExceptionObject);
if (_settings.UnhandledExceptionPolicy == UnhandledExceptionPolicyCode.TakeNoAction)
return;
Log.Fatal("The service threw an unhandled exception", (Exception)e.ExceptionObject);
if (_settings.UnhandledExceptionPolicy == UnhandledExceptionPolicyCode.LogErrorOnly)
return;
ExitCode = (int)AsService.ExitCode.AbnormalExit;
_unhandledException = (Exception)e.ExceptionObject;
Stop();
// it isn't likely that a TPL thread should land here, but if it does let's no block it
if (Task.CurrentId.HasValue)
return;
int deadThreadId = Interlocked.Increment(ref _deadThread);
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Unhandled Exception " + deadThreadId;
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
}
class WindowsSessionChangedArguments :
SessionChangedArguments
{
public WindowsSessionChangedArguments(SessionChangeDescription changeDescription)
{
ReasonCode = (SessionChangeReasonCode)Enum.ToObject(typeof(SessionChangeReasonCode), (int)changeDescription.Reason);
SessionId = changeDescription.SessionId;
}
public SessionChangeReasonCode ReasonCode { get; }
public int SessionId { get; }
}
class WindowsPowerEventArguments :
PowerEventArguments
{
public WindowsPowerEventArguments(PowerBroadcastStatus powerStatus)
{
EventCode = (PowerEventCode)Enum.ToObject(typeof(PowerEventCode), (int)powerStatus);
}
public PowerEventCode EventCode { get; }
}
}
}

@ -1,8 +0,0 @@
using ZeroLevel.Services.AsService.Builder;
namespace ZeroLevel.Services.AsService
{
public delegate HostBuilder HostBuilderFactory(HostEnvironment environment, HostSettings settings);
public delegate ServiceBuilder ServiceBuilderFactory(HostSettings settings);
public delegate EnvironmentBuilder EnvironmentBuilderFactory(HostConfigurator configurator);
}

@ -1,10 +1,19 @@
using System; using System;
using System.Net;
using ZeroLevel.Models; using ZeroLevel.Models;
namespace ZeroLevel.Network namespace ZeroLevel.Network
{ {
public interface IClient public interface IClient
: IDisposable
{ {
IPEndPoint EndPoint { get; }
SocketClientStatus Status { get; }
IRouter Router { get; }
ISocketClient Socket { get; }
InvokeResult Send<T>(T message);
InvokeResult Send(string inbox); InvokeResult Send(string inbox);
InvokeResult Send(string inbox, byte[] data); InvokeResult Send(string inbox, byte[] data);
InvokeResult Send<T>(string inbox, T message); InvokeResult Send<T>(string inbox, T message);

@ -17,7 +17,7 @@ namespace ZeroLevel.Network
IServiceRoutesStorage RoutesStorage { get; } IServiceRoutesStorage RoutesStorage { get; }
IServiceRoutesStorage DiscoveryStorage { get; } IServiceRoutesStorage DiscoveryStorage { get; }
ExClient GetConnection(string alias); IClient GetConnection(string alias);
ExClient GetConnection(IPEndPoint endpoint); IClient GetConnection(IPEndPoint endpoint);
} }
} }

@ -31,6 +31,6 @@ namespace ZeroLevel.Network
IEnumerable<InboxServiceDescription> CollectInboxInfo(); IEnumerable<InboxServiceDescription> CollectInboxInfo();
event Action<ISocketClient> OnDisconnect; event Action<ISocketClient> OnDisconnect;
event Action<ExClient> OnConnect; event Action<IClient> OnConnect;
} }
} }

@ -13,8 +13,6 @@ namespace ZeroLevel.Network
IRouter Router { get; } IRouter Router { get; }
void ForceConnect();
void UseKeepAlive(TimeSpan period);
void Send(Frame data); void Send(Frame data);
void Request(Frame data, Action<byte[]> callback, Action<string> fail = null); void Request(Frame data, Action<byte[]> callback, Action<string> fail = null);
void Response(byte[] data, int identity); void Response(byte[] data, int identity);

@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Network namespace ZeroLevel.Network
{ {
public sealed class ExClient internal sealed class ExClient
: IClient, IDisposable : IClient, IDisposable
{ {
private readonly ISocketClient _client; private readonly ISocketClient _client;
@ -19,8 +19,6 @@ namespace ZeroLevel.Network
_client = client; _client = client;
} }
public void ForceConnect() => _client.ForceConnect();
public InvokeResult Send(string inbox) public InvokeResult Send(string inbox)
{ {
try try

@ -592,7 +592,7 @@ namespace ZeroLevel.Network
} }
#endregion #endregion
public ExClient GetConnection(string alias) public IClient GetConnection(string alias)
{ {
if (_update_discovery_table_task != -1) if (_update_discovery_table_task != -1)
{ {
@ -622,7 +622,7 @@ namespace ZeroLevel.Network
return null; return null;
} }
public ExClient GetConnection(IPEndPoint endpoint) public IClient GetConnection(IPEndPoint endpoint)
{ {
try try
{ {
@ -750,7 +750,7 @@ namespace ZeroLevel.Network
return null; return null;
} }
private IEnumerable<ExClient> GetClientEnumerator(string serviceKey) private IEnumerable<IClient> GetClientEnumerator(string serviceKey)
{ {
IEnumerable<IPEndPoint> candidates; IEnumerable<IPEndPoint> candidates;
try try
@ -766,7 +766,7 @@ namespace ZeroLevel.Network
{ {
foreach (var endpoint in candidates) foreach (var endpoint in candidates)
{ {
ExClient transport; IClient transport;
try try
{ {
transport = _cachee.GetClient(endpoint, true); transport = _cachee.GetClient(endpoint, true);
@ -786,7 +786,7 @@ namespace ZeroLevel.Network
} }
} }
private IEnumerable<ExClient> GetClientEnumeratorByType(string serviceType) private IEnumerable<IClient> GetClientEnumeratorByType(string serviceType)
{ {
IEnumerable<IPEndPoint> candidates; IEnumerable<IPEndPoint> candidates;
try try
@ -802,7 +802,7 @@ namespace ZeroLevel.Network
{ {
foreach (var endpoint in candidates) foreach (var endpoint in candidates)
{ {
ExClient transport; IClient transport;
try try
{ {
transport = _cachee.GetClient(endpoint, true); transport = _cachee.GetClient(endpoint, true);
@ -822,7 +822,7 @@ namespace ZeroLevel.Network
} }
} }
private IEnumerable<ExClient> GetClientEnumeratorByGroup(string serviceGroup) private IEnumerable<IClient> GetClientEnumeratorByGroup(string serviceGroup)
{ {
IEnumerable<IPEndPoint> candidates; IEnumerable<IPEndPoint> candidates;
try try
@ -838,7 +838,7 @@ namespace ZeroLevel.Network
{ {
foreach (var service in candidates) foreach (var service in candidates)
{ {
ExClient transport; IClient transport;
try try
{ {
transport = _cachee.GetClient(service, true); transport = _cachee.GetClient(service, true);
@ -863,7 +863,7 @@ namespace ZeroLevel.Network
/// <param name="serviceKey">Service key</param> /// <param name="serviceKey">Service key</param>
/// <param name="callHandler">Service call code</param> /// <param name="callHandler">Service call code</param>
/// <returns>true - service called succesfully</returns> /// <returns>true - service called succesfully</returns>
private bool CallService(string serviceKey, Func<ExClient, bool> callHandler) private bool CallService(string serviceKey, Func<IClient, bool> callHandler)
{ {
IEnumerable<IPEndPoint> candidates; IEnumerable<IPEndPoint> candidates;
try try
@ -883,7 +883,7 @@ namespace ZeroLevel.Network
var success = false; var success = false;
foreach (var endpoint in candidates) foreach (var endpoint in candidates)
{ {
ExClient transport; IClient transport;
try try
{ {
transport = _cachee.GetClient(endpoint, true); transport = _cachee.GetClient(endpoint, true);
@ -911,7 +911,7 @@ namespace ZeroLevel.Network
return success; return success;
} }
private IEnumerable<Tresp> _RequestBroadcast<Treq, Tresp>(List<ExClient> clients, string inbox, Treq data) private IEnumerable<Tresp> _RequestBroadcast<Treq, Tresp>(List<IClient> clients, string inbox, Treq data)
{ {
var response = new List<Tresp>(); var response = new List<Tresp>();
using (var waiter = new CountdownEvent(clients.Count)) using (var waiter = new CountdownEvent(clients.Count))
@ -939,7 +939,7 @@ namespace ZeroLevel.Network
return response; return response;
} }
private IEnumerable<Tresp> _RequestBroadcast<Tresp>(List<ExClient> clients, string inbox) private IEnumerable<Tresp> _RequestBroadcast<Tresp>(List<IClient> clients, string inbox)
{ {
var response = new List<Tresp>(); var response = new List<Tresp>();
using (var waiter = new CountdownEvent(clients.Count)) using (var waiter = new CountdownEvent(clients.Count))

@ -25,13 +25,13 @@ namespace ZeroLevel.Network.FileTransfer
_uploadFileThread.Start(); _uploadFileThread.Start();
} }
public void Send(ExClient client, string fileName, Action<string> completeHandler = null, Action<string, string> errorHandler = null) public void Send(IClient client, string fileName, Action<string> completeHandler = null, Action<string, string> errorHandler = null)
{ {
if (client == null) return; if (client == null) return;
PushTransferTask(client, fileName, completeHandler, errorHandler); PushTransferTask(client, fileName, completeHandler, errorHandler);
} }
private void PushTransferTask(ExClient client, string filePath, Action<string> completeHandler = null, Action<string, string> errorHandler = null) private void PushTransferTask(IClient client, string filePath, Action<string> completeHandler = null, Action<string, string> errorHandler = null)
{ {
if (client == null) if (client == null)
{ {
@ -74,7 +74,7 @@ namespace ZeroLevel.Network.FileTransfer
} }
} }
public bool Connected(ExClient client, TimeSpan timeout) public bool Connected(IClient client, TimeSpan timeout)
{ {
bool connected = false; bool connected = false;
using (var waiter = new ManualResetEvent(false)) using (var waiter = new ManualResetEvent(false))
@ -85,7 +85,7 @@ namespace ZeroLevel.Network.FileTransfer
return connected; return connected;
} }
private static bool Send<T>(ExClient client, string inbox, T frame, private static bool Send<T>(IClient client, string inbox, T frame,
bool resendWhenConnectionError, bool resendWhenServerError) bool resendWhenConnectionError, bool resendWhenServerError)
{ {
bool sended = false; bool sended = false;

@ -7,6 +7,6 @@ namespace ZeroLevel.Network.FileTransfer
public string FilePath; public string FilePath;
public Action<string> CompletedHandler; public Action<string> CompletedHandler;
public Action<string, string> ErrorHandler; public Action<string, string> ErrorHandler;
public ExClient Client; public IClient Client;
} }
} }

@ -12,6 +12,8 @@ namespace ZeroLevel.Network
: BaseSocket, ISocketClient : BaseSocket, ISocketClient
{ {
#region Private #region Private
#region Queues
private class IncomingFrame private class IncomingFrame
{ {
private IncomingFrame() { } private IncomingFrame() { }
@ -32,25 +34,24 @@ namespace ZeroLevel.Network
public static SendFrame NewFrame() => new SendFrame(); public static SendFrame NewFrame() => new SendFrame();
} }
private Socket _clientSocket; private ObjectPool<IncomingFrame> _incoming_frames_pool = new ObjectPool<IncomingFrame>(() => IncomingFrame.NewFrame());
private NetworkStream _stream; private ObjectPool<SendFrame> _send_frames_pool = new ObjectPool<SendFrame>(() => SendFrame.NewFrame());
private FrameParser _parser = new FrameParser(); private BlockingCollection<IncomingFrame> _incoming_queue = new BlockingCollection<IncomingFrame>();
private readonly RequestBuffer _requests = new RequestBuffer(); private BlockingCollection<SendFrame> _send_queue = new BlockingCollection<SendFrame>(BaseSocket.MAX_SEND_QUEUE_SIZE);
#endregion
private bool _socket_freezed = false; // используется для связи сервер-клиент, запрещает пересоздание сокета private Socket _clientSocket;
private int _current_heartbeat_period_in_ms = 0; private AsyncCallback _receiveAsyncCallback;
private long _heartbeat_key = -1; private FrameParser _parser;
private long _last_rw_time = DateTime.UtcNow.Ticks; private readonly RequestBuffer _requests = new RequestBuffer();
private readonly byte[] _buffer = new byte[DEFAULT_RECEIVE_BUFFER_SIZE]; private readonly byte[] _buffer = new byte[DEFAULT_RECEIVE_BUFFER_SIZE];
private bool _socket_freezed = false; // используется для связи сервер-клиент, запрещает пересоздание сокета
private readonly object _reconnection_lock = new object(); private readonly object _reconnection_lock = new object();
private long _heartbeat_key;
private Thread _sendThread; private Thread _sendThread;
private Thread _receiveThread; private Thread _receiveThread;
private BlockingCollection<IncomingFrame> _incoming_queue = new BlockingCollection<IncomingFrame>();
private BlockingCollection<SendFrame> _send_queue = new BlockingCollection<SendFrame>(BaseSocket.MAX_SEND_QUEUE_SIZE);
private ObjectPool<IncomingFrame> _incoming_frames_pool = new ObjectPool<IncomingFrame>(() => IncomingFrame.NewFrame());
private ObjectPool<SendFrame> _send_frames_pool = new ObjectPool<SendFrame>(() => SendFrame.NewFrame());
#endregion Private #endregion Private
public IRouter Router { get; } public IRouter Router { get; }
@ -59,25 +60,44 @@ namespace ZeroLevel.Network
public SocketClient(IPEndPoint ep, IRouter router) public SocketClient(IPEndPoint ep, IRouter router)
{ {
try
{
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_clientSocket.SetIPProtectionLevel(IPProtectionLevel.Unrestricted);
_clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
_clientSocket.Connect(ep);
OnConnect(this);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[SocketClient.ctor] connection fault. Endpoint: {Endpoint.Address}:{Endpoint.Port}");
Broken();
return;
}
Router = router; Router = router;
Endpoint = ep; Endpoint = ep;
_parser.OnIncoming += _parser_OnIncoming; _parser = new FrameParser(_parser_OnIncoming);
_receiveAsyncCallback = new AsyncCallback(ReceiveAsyncCallback);
Working();
StartInternalThreads(); StartInternalThreads();
EnsureConnection(); StartReceive();
} }
public SocketClient(Socket socket, IRouter router) public SocketClient(Socket socket, IRouter router)
{ {
Router = router; Router = router;
_socket_freezed = true;
_clientSocket = socket; _clientSocket = socket;
_stream = new NetworkStream(_clientSocket, true);
Endpoint = (IPEndPoint)_clientSocket.RemoteEndPoint; Endpoint = (IPEndPoint)_clientSocket.RemoteEndPoint;
_parser.OnIncoming += _parser_OnIncoming; _parser = new FrameParser(_parser_OnIncoming);
StartInternalThreads(); _receiveAsyncCallback = new AsyncCallback(ReceiveAsyncCallback);
_socket_freezed = true;
Working(); Working();
_stream.BeginRead(_buffer, 0, DEFAULT_RECEIVE_BUFFER_SIZE, ReceiveAsyncCallback, null); StartInternalThreads();
StartReceive();
} }
private void StartInternalThreads() private void StartInternalThreads()
@ -89,6 +109,28 @@ namespace ZeroLevel.Network
_receiveThread = new Thread(IncomingFramesJob); _receiveThread = new Thread(IncomingFramesJob);
_receiveThread.IsBackground = true; _receiveThread.IsBackground = true;
_receiveThread.Start(); _receiveThread.Start();
_heartbeat_key = Sheduller.RemindEvery(TimeSpan.FromMilliseconds(MINIMUM_HEARTBEAT_UPDATE_PERIOD_MS), Heartbeat);
}
private void StartReceive()
{
try
{
_clientSocket.BeginReceive(_buffer, 0, DEFAULT_RECEIVE_BUFFER_SIZE, SocketFlags.None, ReceiveAsyncCallback, null);
}
catch (NullReferenceException)
{
Broken();
Log.SystemError("[SocketClient.TryConnect] Client : Null Reference Exception - On Connect (begin receive section)");
_clientSocket.Disconnect(false);
}
catch (SocketException e)
{
Broken();
Log.SystemError(e, "[SocketClient.TryConnect] Client : Exception - On Connect (begin receive section)");
_clientSocket.Disconnect(false);
}
} }
#region API #region API
@ -99,6 +141,7 @@ namespace ZeroLevel.Network
public void Request(Frame frame, Action<byte[]> callback, Action<string> fail = null) public void Request(Frame frame, Action<byte[]> callback, Action<string> fail = null)
{ {
if (frame == null) throw new ArgumentNullException(nameof(frame)); if (frame == null) throw new ArgumentNullException(nameof(frame));
if (Status != SocketClientStatus.Working) throw new Exception($"[SocketClient.Request] Socket status: {Status}");
var data = NetworkPacketFactory.Reqeust(MessageSerializer.Serialize(frame), out int id); var data = NetworkPacketFactory.Reqeust(MessageSerializer.Serialize(frame), out int id);
frame.Release(); frame.Release();
@ -118,14 +161,10 @@ namespace ZeroLevel.Network
} }
} }
public void ForceConnect()
{
EnsureConnection();
}
public void Send(Frame frame) public void Send(Frame frame)
{ {
if (frame == null) throw new ArgumentNullException(nameof(frame)); if (frame == null) throw new ArgumentNullException(nameof(frame));
if (Status != SocketClientStatus.Working) throw new Exception($"[SocketClient.Send] Socket status: {Status}");
var data = NetworkPacketFactory.Message(MessageSerializer.Serialize(frame)); var data = NetworkPacketFactory.Message(MessageSerializer.Serialize(frame));
frame.Release(); frame.Release();
@ -146,6 +185,7 @@ namespace ZeroLevel.Network
public void Response(byte[] data, int identity) public void Response(byte[] data, int identity)
{ {
if (data == null) throw new ArgumentNullException(nameof(data)); if (data == null) throw new ArgumentNullException(nameof(data));
if (Status != SocketClientStatus.Working) throw new Exception($"[SocketClient.Response] Socket status: {Status}");
if (!_send_queue.IsAddingCompleted) if (!_send_queue.IsAddingCompleted)
{ {
while (_send_queue.Count >= MAX_SEND_QUEUE_SIZE) while (_send_queue.Count >= MAX_SEND_QUEUE_SIZE)
@ -159,23 +199,6 @@ namespace ZeroLevel.Network
_send_queue.Add(sf); _send_queue.Add(sf);
} }
} }
public void UseKeepAlive(TimeSpan period)
{
if (_heartbeat_key != -1)
{
Sheduller.Remove(_heartbeat_key);
}
if (period != TimeSpan.Zero && period.TotalMilliseconds > MINIMUM_HEARTBEAT_UPDATE_PERIOD_MS)
{
_current_heartbeat_period_in_ms = (int)period.TotalMilliseconds;
_heartbeat_key = Sheduller.RemindEvery(period, Heartbeat);
}
else
{
_current_heartbeat_period_in_ms = 0;
}
}
#endregion #endregion
#region Private methods #region Private methods
@ -197,50 +220,35 @@ namespace ZeroLevel.Network
} }
} }
private bool TryConnect() public void ReceiveAsyncCallback(IAsyncResult ar)
{ {
if (Status == SocketClientStatus.Working) try
{
return true;
}
if (Status == SocketClientStatus.Disposed)
{
return false;
}
if (_clientSocket != null)
{ {
try var count = _clientSocket.EndReceive(ar);
if (count > 0)
{ {
_stream?.Close(); _parser.Push(_buffer, count);
_stream?.Dispose();
_clientSocket.Dispose();
} }
catch else
{ {
/* ignore */ // TODO or not TODO
Thread.Sleep(1);
} }
_clientSocket = null; StartReceive();
_stream = null;
} }
try catch (ObjectDisposedException)
{ {
_clientSocket = MakeClientSocket(); /// Nothing
_clientSocket.Connect(Endpoint);
_stream = new NetworkStream(_clientSocket, true);
_stream.BeginRead(_buffer, 0, DEFAULT_RECEIVE_BUFFER_SIZE, ReceiveAsyncCallback, null);
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemError(ex, "[SocketClient.TryConnect] Connection fault"); Log.SystemError(ex, $"[SocketClient.ReceiveAsyncCallback] Error read data");
Broken(); Broken();
return false; OnDisconnect(this);
} }
Working();
OnConnect(this);
return true;
} }
public void EnsureConnection() private void EnsureConnection()
{ {
if (_socket_freezed) if (_socket_freezed)
{ {
@ -254,10 +262,7 @@ namespace ZeroLevel.Network
} }
if (Status != SocketClientStatus.Working) if (Status != SocketClientStatus.Working)
{ {
if (false == TryConnect()) throw new Exception("No connection");
{
throw new Exception("No connection");
}
} }
} }
} }
@ -276,55 +281,11 @@ namespace ZeroLevel.Network
return; return;
} }
_requests.TestForTimeouts(); _requests.TestForTimeouts();
try var info = _send_frames_pool.Allocate();
{ info.isRequest = false;
var info = _send_frames_pool.Allocate(); info.identity = 0;
info.isRequest = false; info.data = NetworkPacketFactory.KeepAliveMessage();
info.identity = 0; _send_queue.Add(info);
info.data = NetworkPacketFactory.KeepAliveMessage();
_send_queue.Add(info);
}
catch (Exception ex)
{
Log.SystemError(ex, "[SocketClient.Heartbeat.Request]");
}
var diff_request_ms = ((DateTime.UtcNow.Ticks - _last_rw_time) / TimeSpan.TicksPerMillisecond);
if (diff_request_ms > (_current_heartbeat_period_in_ms * 2))
{
var port = (_clientSocket.LocalEndPoint as IPEndPoint)?.Port;
Log.Debug($"[SocketClient.Heartbeat] server disconnected, because last data was more thas {diff_request_ms} ms ago. Client port {port}");
Broken();
}
}
private void ReceiveAsyncCallback(IAsyncResult ar)
{
try
{
var count = _stream.EndRead(ar);
if (count > 0)
{
_parser.Push(_buffer, count);
_last_rw_time = DateTime.UtcNow.Ticks;
}
else
{
// TODO or not TODO
Thread.Sleep(1);
}
EnsureConnection();
_stream.BeginRead(_buffer, 0, DEFAULT_RECEIVE_BUFFER_SIZE, ReceiveAsyncCallback, null);
}
catch (ObjectDisposedException)
{
/// Nothing
}
catch (Exception ex)
{
Log.SystemError(ex, $"[SocketClient.ReceiveAsyncCallback] Error read data");
Broken();
OnDisconnect(this);
}
} }
private void IncomingFramesJob() private void IncomingFramesJob()
@ -334,7 +295,42 @@ namespace ZeroLevel.Network
{ {
try try
{ {
frame = _incoming_queue.Take(); if (_incoming_queue.TryTake(out frame, 100))
{
try
{
switch (frame.type)
{
case FrameType.Message:
Router?.HandleMessage(MessageSerializer.Deserialize<Frame>(frame.data), this);
break;
case FrameType.Request:
{
Router?.HandleRequest(MessageSerializer.Deserialize<Frame>(frame.data), this, frame.identity, (id, response) =>
{
if (response != null)
{
this.Response(response, id);
}
});
}
break;
case FrameType.Response:
{
_requests.Success(frame.identity, frame.data);
}
break;
}
}
catch (Exception ex)
{
Log.SystemError(ex, "[SocketClient.IncomingFramesJob] Handle frame");
}
finally
{
_incoming_frames_pool.Free(frame);
}
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -350,55 +346,41 @@ namespace ZeroLevel.Network
} }
continue; continue;
} }
try
{
switch (frame.type)
{
case FrameType.Message:
Router?.HandleMessage(MessageSerializer.Deserialize<Frame>(frame.data), this);
break;
case FrameType.Request:
{
Router?.HandleRequest(MessageSerializer.Deserialize<Frame>(frame.data), this, frame.identity, (id, response) =>
{
if (response != null)
{
this.Response(response, id);
}
});
}
break;
case FrameType.Response:
{
_requests.Success(frame.identity, frame.data);
}
break;
}
}
catch (Exception ex)
{
Log.SystemError(ex, "[SocketClient.IncomingFramesJob] Handle frame");
}
finally
{
_incoming_frames_pool.Free(frame);
}
} }
} }
private void SendFramesJob() private void SendFramesJob()
{ {
SendFrame frame = null; SendFrame frame = null;
int unsuccess = 0;
while (Status != SocketClientStatus.Disposed && !_send_queue.IsCompleted) while (Status != SocketClientStatus.Disposed && !_send_queue.IsCompleted)
{ {
try try
{ {
frame = _send_queue.Take(); if (_send_queue.TryTake(out frame, 100))
{
try
{
if (frame.isRequest)
{
_requests.StartSend(frame.identity);
}
_clientSocket.Send(frame.data, frame.data.Length, SocketFlags.None);
}
catch (Exception ex)
{
Log.SystemError(ex, $"[SocketClient.SendFramesJob] _str_clientSocketeam.Send");
Broken();
OnDisconnect(this);
}
finally
{
_send_frames_pool.Free(frame);
}
}
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemError(ex, "[SocketClient.SendFramesJob] send_queue.Take"); Log.SystemError(ex, "[SocketClient.SendFramesJob] send_queue.TryTake");
if (Status != SocketClientStatus.Disposed) if (Status != SocketClientStatus.Disposed)
{ {
_send_queue.Dispose(); _send_queue.Dispose();
@ -410,94 +392,11 @@ namespace ZeroLevel.Network
} }
continue; continue;
} }
while (_stream?.CanWrite == false || Status != SocketClientStatus.Working)
{
try
{
EnsureConnection();
}
catch (Exception ex)
{
Log.SystemError(ex, "[SocketClient.SendFramesJob] Connection broken");
}
if (Status == SocketClientStatus.Disposed)
{
return;
}
if (Status == SocketClientStatus.Broken)
{
unsuccess++;
if (unsuccess > 30) unsuccess = 30;
}
if (Status == SocketClientStatus.Working)
{
unsuccess = 0;
break;
}
Thread.Sleep(unsuccess * 128);
}
try
{
if (frame.isRequest)
{
_requests.StartSend(frame.identity);
}
_stream.Write(frame.data, 0, frame.data.Length);
_last_rw_time = DateTime.UtcNow.Ticks;
}
catch (Exception ex)
{
Log.SystemError(ex, $"[SocketClient.SendFramesJob] _stream.Write");
Broken();
OnDisconnect(this);
}
finally
{
_send_frames_pool.Free(frame);
}
} }
} }
#endregion #endregion
#region Helper
private static Socket MakeClientSocket()
{
var s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.SetIPProtectionLevel(IPProtectionLevel.Unrestricted);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
return s;
}
/* TODO to test
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
try
{
// Workaround for: https://github.com/dotnet/corefx/issues/24430
using (cancellationToken.Register(Dispose))
{
if (cancellationToken.IsCancellationRequested)
{
return 0;
}
return await _stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
}
}
catch (IOException exception)
{
if (exception.InnerException is SocketException socketException)
{
ExceptionDispatchInfo.Capture(socketException).Throw();
}
throw;
}
}
*/
#endregion Helper
public override void Dispose() public override void Dispose()
{ {
if (Status == SocketClientStatus.Working) if (Status == SocketClientStatus.Working)
@ -506,8 +405,15 @@ namespace ZeroLevel.Network
} }
Disposed(); Disposed();
Sheduller.Remove(_heartbeat_key); Sheduller.Remove(_heartbeat_key);
_stream?.Close(); try
_stream?.Dispose(); {
_clientSocket?.Close();
_clientSocket?.Dispose();
}
catch (Exception ex)
{
Log.Error(ex, "[SocketClient.Dispose]");
}
} }
} }
} }

@ -18,7 +18,7 @@ namespace ZeroLevel.Network
private readonly IRouter _router; private readonly IRouter _router;
public IPEndPoint LocalEndpoint { get; } public IPEndPoint LocalEndpoint { get; }
public event Action<ISocketClient> OnDisconnect = _ => { }; public event Action<ISocketClient> OnDisconnect = _ => { };
public event Action<ExClient> OnConnect = _ => { }; public event Action<IClient> OnConnect = _ => { };
public IEnumerable<IPEndPoint> ConnectionList public IEnumerable<IPEndPoint> ConnectionList
{ {
@ -79,7 +79,6 @@ namespace ZeroLevel.Network
var connection = new SocketClient(client_socket, _router); var connection = new SocketClient(client_socket, _router);
connection.OnDisconnect += Connection_OnDisconnect; connection.OnDisconnect += Connection_OnDisconnect;
_connections[connection.Endpoint] = new ExClient(connection); _connections[connection.Endpoint] = new ExClient(connection);
connection.UseKeepAlive(TimeSpan.FromMilliseconds(BaseSocket.MINIMUM_HEARTBEAT_UPDATE_PERIOD_MS));
ConnectEventRise(_connections[connection.Endpoint]); ConnectEventRise(_connections[connection.Endpoint]);
} }
catch (Exception ex) catch (Exception ex)

@ -15,7 +15,7 @@ namespace ZeroLevel.Network
internal IEnumerable<SocketServer> ServerList => _serverInstances.Values; internal IEnumerable<SocketServer> ServerList => _serverInstances.Values;
public ExClient GetClient(IPEndPoint endpoint, bool use_cachee, IRouter router = null) public IClient GetClient(IPEndPoint endpoint, bool use_cachee, IRouter router = null)
{ {
if (use_cachee) if (use_cachee)
{ {
@ -41,12 +41,10 @@ namespace ZeroLevel.Network
instance = null; instance = null;
} }
instance = new ExClient(new SocketClient(endpoint, router ?? new Router())); instance = new ExClient(new SocketClient(endpoint, router ?? new Router()));
instance.ForceConnect();
if (instance.Status == SocketClientStatus.Initialized if (instance.Status == SocketClientStatus.Initialized
|| instance.Status == SocketClientStatus.Working) || instance.Status == SocketClientStatus.Working)
{ {
_clientInstances[key] = instance; _clientInstances[key] = instance;
instance.Socket.UseKeepAlive(TimeSpan.FromMilliseconds(BaseSocket.MINIMUM_HEARTBEAT_UPDATE_PERIOD_MS));
return instance; return instance;
} }
} }

@ -129,12 +129,17 @@ namespace ZeroLevel.Network
#endregion private models #endregion private models
public event Action<FrameType, int, byte[]> OnIncoming; private Action<FrameType, int, byte[]> _incomingDataHandler;
private readonly _Accum _accum = new _Accum(); private readonly _Accum _accum = new _Accum();
private ParserState _state = ParserState.WaitNew; private ParserState _state = ParserState.WaitNew;
private readonly object _push_lock = new object(); private readonly object _push_lock = new object();
public FrameParser(Action<FrameType, int, byte[]> incomingDataHandler)
{
_incomingDataHandler = incomingDataHandler;
}
/// <summary> /// <summary>
/// Parse with state machine /// Parse with state machine
/// </summary> /// </summary>
@ -150,7 +155,7 @@ namespace ZeroLevel.Network
{ {
try try
{ {
OnIncoming?.Invoke(type, identity, payload); _incomingDataHandler?.Invoke(type, identity, payload);
} }
catch (Exception ex) catch (Exception ex)
{ {

@ -14,7 +14,7 @@ namespace ZeroLevel.Network
: IRouter : IRouter
{ {
public event Action<ISocketClient> OnDisconnect = _ => { }; // must be never rised public event Action<ISocketClient> OnDisconnect = _ => { }; // must be never rised
public event Action<ExClient> OnConnect = _ => { }; // must be never rised public event Action<IClient> OnConnect = _ => { }; // must be never rised
#region Routing #region Routing
@ -398,7 +398,7 @@ namespace ZeroLevel.Network
: IRouter : IRouter
{ {
public event Action<ISocketClient> OnDisconnect = _ => { }; public event Action<ISocketClient> OnDisconnect = _ => { };
public event Action<ExClient> OnConnect = _ => { }; public event Action<IClient> OnConnect = _ => { };
public void HandleMessage(Frame frame, ISocketClient client) { } public void HandleMessage(Frame frame, ISocketClient client) { }
public void HandleRequest(Frame frame, ISocketClient client, int identity, Action<int, byte[]> handler) { } public void HandleRequest(Frame frame, ISocketClient client, int identity, Action<int, byte[]> handler) { }
public IServer RegisterInbox(string inbox, MessageHandler handler) { return this; } public IServer RegisterInbox(string inbox, MessageHandler handler) { return this; }

@ -45,8 +45,4 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Services\AsService\DotNetCore\" />
</ItemGroup>
</Project> </Project>

Loading…
Cancel
Save

Powered by TurnKey Linux.