Beispiel #1
0
        public StoreBuilder <TState> UseExceptionHandler(Action <Exception> exceptionHandler)
        {
            _exceptionHandler = new ServiceDescriptor(
                typeof(IExceptionHandler),
                _ => {
                return(new ActionExceptionHandler(exceptionHandler));
            },
                _serviceLifetime);

            return(this);
        }
    /// <summary>
    ///     This fixes an issue for .NET6 Preview1, that in AddRazorRuntimeCompilation cannot remove the existing
    ///     IViewCompilerProvider.
    /// </summary>
    /// <remarks>
    ///     When running .NET6 Preview1 there is an issue with looks to be fixed when running ASP.NET Core 6.
    ///     This issue is because the default implementation of IViewCompilerProvider has changed, so the
    ///     AddRazorRuntimeCompilation extension can't remove the default and replace with the runtimeviewcompiler.
    ///     This method basically does the same as the ASP.NET Core 6 version of AddRazorRuntimeCompilation
    ///     https://github.com/dotnet/aspnetcore/blob/f7dc5e24af7f9692a1db66741954b90b42d84c3a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/DependencyInjection/RazorRuntimeCompilationMvcCoreBuilderExtensions.cs#L71-L80
    ///     While running .NET5 this does nothing as the ImplementationType has another FullName, and this is handled by the
    ///     .NET5 version of AddRazorRuntimeCompilation
    /// </remarks>
    private static void FixForDotnet6Preview1(IServiceCollection services)
    {
        ServiceDescriptor?compilerProvider = services.FirstOrDefault(f =>
                                                                     f.ServiceType == typeof(IViewCompilerProvider) &&
                                                                     f.ImplementationType?.Assembly == typeof(IViewCompilerProvider).Assembly &&
                                                                     f.ImplementationType.FullName == "Microsoft.AspNetCore.Mvc.Razor.Compilation.DefaultViewCompiler");

        if (compilerProvider != null)
        {
            services.Remove(compilerProvider);
        }
    }
Beispiel #3
0
        public static void AutoCrossWireAspNetComponents(
            this Container container, IServiceProvider appServices)
        {
            Requires.IsNotNull(container, nameof(container));
            Requires.IsNotNull(appServices, nameof(appServices));

            var services = (IServiceCollection?)container.ContainerScope.GetItem(CrossWireContextKey);

            if (services is null)
            {
                throw new InvalidOperationException(
                          "To use this method, please make sure cross-wiring is enabled, by invoking " +
                          $"the {nameof(EnableSimpleInjectorCrossWiring)} extension method as part of the " +
                          "ConfigureServices method of the Startup class. " + Environment.NewLine +
                          "See https://simpleinjector.org/aspnetcore for more information.");
            }

            if (container.Options.DefaultScopedLifestyle is null)
            {
                throw new InvalidOperationException(
                          "To be able to allow auto cross-wiring, please ensure that the container is configured " +
                          "with a default scoped lifestyle by setting the Container.Options" +
                          ".DefaultScopedLifestyle property with the required scoped lifestyle for your type of " +
                          "application. In ASP.NET Core, the typical lifestyle to use is the " +
                          $"{nameof(AsyncScopedLifestyle)}. " + Environment.NewLine +
                          "See: https://simpleinjector.org/lifestyles#scoped");
            }

            CrossWireServiceScope(container, appServices);

            container.ResolveUnregisteredType += (s, e) =>
            {
                if (e.Handled)
                {
                    return;
                }

                Type serviceType = e.UnregisteredServiceType;

                ServiceDescriptor?descriptor = FindServiceDescriptor(services, serviceType);

                if (descriptor != null)
                {
                    Lifestyle lifestyle = ToLifestyle(descriptor.Lifetime);

                    Registration registration = lifestyle == Lifestyle.Singleton
                        ? CreateSingletonRegistration(container, serviceType, appServices)
                        : CreateNonSingletonRegistration(container, serviceType, appServices, lifestyle);

                    e.Register(registration);
                }
            };
        }
Beispiel #4
0
        private static IServiceCollection RemoveService <TService>(
            this IServiceCollection services)
        {
            ServiceDescriptor?serviceDescriptor =
                services.FirstOrDefault(t => t.ServiceType == typeof(TService));

            if (serviceDescriptor != null)
            {
                services.Remove(serviceDescriptor);
            }

            return(services);
        }
        protected bool TryAddService(ServiceDescriptor descriptor, [NotNullWhen(true)] out ServiceDescriptor?addedDescriptor)
#endif
        {
            int count = Services.Count;

            Services.TryAddEnumerable(descriptor);
            if (count != Services.Count)
            {
                addedDescriptor = descriptor;
                return(true);
            }
            addedDescriptor = null;
            return(false);
        }
        /// <summary>
        /// Removes all services of type <paramref name="serviceType"/> in <see cref="IServiceCollection"/>.
        /// </summary>
        /// <param name="collection">The <see cref="IServiceCollection"/>.</param>
        /// <param name="serviceType">The service type to remove.</param>
        /// <returns>The <see cref="IServiceCollection"/> for chaining.</returns>
        public static IServiceCollection RemoveAll(this IServiceCollection collection, Type serviceType)
        {
            ThrowHelper.ThrowIfNull(serviceType);

            for (int i = collection.Count - 1; i >= 0; i--)
            {
                ServiceDescriptor?descriptor = collection[i];
                if (descriptor.ServiceType == serviceType)
                {
                    collection.RemoveAt(i);
                }
            }

            return(collection);
        }
Beispiel #7
0
        public void OnServiceMethodDiscovery(ServiceMethodProviderContext <TService> context)
        {
            var bindMethodInfo = BindMethodFinder.GetBindMethod(typeof(TService));

            // Invoke BindService(ServiceBinderBase, BaseType)
            if (bindMethodInfo != null)
            {
                // The second parameter is always the service base type
                var serviceParameter = bindMethodInfo.GetParameters()[1];

                ServiceDescriptor?serviceDescriptor = null;
                try
                {
                    serviceDescriptor = ServiceDescriptorHelpers.GetServiceDescriptor(bindMethodInfo.DeclaringType !);
                }
                catch (Exception ex)
                {
                    Log.ServiceDescriptorError(_logger, typeof(TService), ex);
                }

                if (serviceDescriptor != null)
                {
                    var binder = new HttpApiProviderServiceBinder <TService>(
                        context,
                        serviceParameter.ParameterType,
                        serviceDescriptor,
                        _globalOptions,
                        _serviceOptions,
                        _serviceProvider,
                        _loggerFactory,
                        _serviceActivator);

                    try
                    {
                        bindMethodInfo.Invoke(null, new object[] { binder, null });
                    }
                    catch (Exception ex)
                    {
                        throw new InvalidOperationException($"Error binding gRPC service '{typeof(TService).Name}'.",
                                                            ex);
                    }
                }
            }
            else
            {
                Log.BindMethodNotFound(_logger, typeof(TService));
            }
        }
Beispiel #8
0
        private static ServiceDescriptor?FindServiceDescriptor(IServiceCollection services, Type serviceType)
        {
            // In case there are multiple descriptors for a given type, .NET Core will use the last
            // descriptor when one instance is resolved. We will have to get this last one as well.
            ServiceDescriptor?descriptor = services.LastOrDefault(d => d.ServiceType == serviceType);

            if (descriptor == null && serviceType.GetTypeInfo().IsGenericType)
            {
                // In case the registration is made as open-generic type, the previous query will return
                // null, and we need to go find the last open generic registration for the service type.
                var serviceTypeDefinition = serviceType.GetTypeInfo().GetGenericTypeDefinition();
                descriptor = services.LastOrDefault(d => d.ServiceType == serviceTypeDefinition);
            }

            return(descriptor);
        }
            /// <summary>
            /// Sets the service descriptor.
            /// </summary>
            /// <param name="descriptor">The service descriptor.</param>
            /// <returns>The builder instance, so that calls can be easily chained.</returns>
            public Builder <TContext> SetServiceDescriptor(ServiceDescriptor descriptor)
            {
                if (descriptor is null)
                {
                    throw new ArgumentNullException(nameof(descriptor));
                }

                var type = descriptor.ServiceType;

                if (!typeof(IOpenIddictValidationHandler <>).MakeGenericType(typeof(TContext)).IsAssignableFrom(type))
                {
                    throw new InvalidOperationException(SR.GetResourceString(SR.ID0104));
                }

                _descriptor = descriptor;

                return(this);
            }
        /// <summary>
        /// Removes all services of type <paramref name="serviceType"/> in <see cref="IServiceCollection"/>.
        /// </summary>
        /// <param name="collection">The <see cref="IServiceCollection"/>.</param>
        /// <param name="serviceType">The service type to remove.</param>
        /// <returns>The <see cref="IServiceCollection"/> for chaining.</returns>
        public static IServiceCollection RemoveAll(this IServiceCollection collection, Type serviceType)
        {
            if (serviceType == null)
            {
                throw new ArgumentNullException(nameof(serviceType));
            }

            for (int i = collection.Count - 1; i >= 0; i--)
            {
                ServiceDescriptor?descriptor = collection[i];
                if (descriptor.ServiceType == serviceType)
                {
                    collection.RemoveAt(i);
                }
            }

            return(collection);
        }
        /// <summary>
        /// Add the token acquisition service.
        /// </summary>
        /// <param name="services">Service collection.</param>
        /// <param name="isTokenAcquisitionSingleton">Specifies if an instance of <see cref="ITokenAcquisition"/> should be a singleton.</param>
        /// <returns>The service collection.</returns>
        /// <example>
        /// This method is typically called from the <c>ConfigureServices(IServiceCollection services)</c> in Startup.cs.
        /// Note that the implementation of the token cache can be chosen separately.
        ///
        /// <code>
        /// // Token acquisition service and its cache implementation as a session cache
        /// services.AddTokenAcquisition()
        /// .AddDistributedMemoryCache()
        /// .AddSession()
        /// .AddSessionBasedTokenCache();
        /// </code>
        /// </example>
        public static IServiceCollection AddTokenAcquisition(
            this IServiceCollection services,
            bool isTokenAcquisitionSingleton = false)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            ServiceDescriptor?tokenAcquisitionService         = services.FirstOrDefault(s => s.ServiceType == typeof(ITokenAcquisition));
            ServiceDescriptor?tokenAcquisitionInternalService = services.FirstOrDefault(s => s.ServiceType == typeof(ITokenAcquisitionInternal));

            if (tokenAcquisitionService != null && tokenAcquisitionInternalService != null)
            {
                if (isTokenAcquisitionSingleton ^ (tokenAcquisitionService.Lifetime == ServiceLifetime.Singleton))
                {
                    // The service was already added, but not with the right lifetime
                    services.Remove(tokenAcquisitionService);
                    services.Remove(tokenAcquisitionInternalService);
                }
                else
                {
                    // The service is already added with the right lifetime
                    return(services);
                }
            }

            // Token acquisition service
            services.AddHttpContextAccessor();
            if (isTokenAcquisitionSingleton)
            {
                services.AddSingleton <ITokenAcquisition, TokenAcquisition>();
                services.AddSingleton <ITokenAcquisitionInternal>(s => (ITokenAcquisitionInternal)s.GetService <ITokenAcquisition>());
            }
            else
            {
                services.AddScoped <ITokenAcquisition, TokenAcquisition>();
                services.AddScoped <ITokenAcquisitionInternal>(s => (ITokenAcquisitionInternal)s.GetService <ITokenAcquisition>());
            }

            return(services);
        }
Beispiel #12
0
        internal static IServiceCollection Decorate <TService>(
            this IServiceCollection services,
            Func <TService, TService> decorate)
            where TService : class
        {
            ServiceDescriptor?serviceToDecorate = services
                                                  .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(TService));

            if (serviceToDecorate != null)
            {
                ServiceDescriptor CreateServiceDescriptor(Func <IServiceProvider, TService> func) =>
                ServiceDescriptor.Describe(typeof(TService), func, serviceToDecorate.Lifetime);

                if (serviceToDecorate.ImplementationFactory != null)
                {
                    services.Replace(CreateServiceDescriptor(provider =>
                    {
                        var service = (TService)serviceToDecorate.ImplementationFactory(provider);
                        return(decorate(service));
                    }));
                }
                else if (serviceToDecorate.ImplementationInstance != null)
                {
                    services.Replace(CreateServiceDescriptor(provider =>
                    {
                        var service = (TService)serviceToDecorate.ImplementationInstance;
                        return(decorate(service));
                    }));
                }
                else if (serviceToDecorate.ImplementationType != null)
                {
                    services.Replace(CreateServiceDescriptor(provider =>
                    {
                        var service = (TService)ActivatorUtilities.CreateInstance(provider, serviceToDecorate.ImplementationType);
                        return(decorate(service));
                    }));
                }
            }

            return(services);
        }
Beispiel #13
0
        private static ApplicationPartManager GetApplicationPartManager(
            this IServiceCollection services, string methodName)
        {
            ServiceDescriptor?descriptor = services
                                           .LastOrDefault(d => d.ServiceType == typeof(ApplicationPartManager));

            if (descriptor is null)
            {
                throw new InvalidOperationException(
                          string.Format(
                              CultureInfo.InvariantCulture,
                              "A registration for the {0} is missing from the ASP.NET Core configuration " +
                              "system. This is most likely caused by a missing call to services.AddMvcCore() or " +
                              "services.AddMvc() as part of the ConfigureServices(IServiceCollection) method of " +
                              "the Startup class. A call to one of those methods will ensure the registration " +
                              "of the {1}.",
                              typeof(ApplicationPartManager).FullName,
                              typeof(ApplicationPartManager).Name));
            }
            else if (descriptor.ImplementationInstance is null)
            {
                throw new InvalidOperationException(
                          string.Format(
                              CultureInfo.InvariantCulture,
                              "Although a registration for {0} exists in the ASP.NET Core configuration system, " +
                              "the registration is not added as an existing instance. This makes it impossible " +
                              "for Simple Injector's {1} method to get this instance from ASP.NET Core's " +
                              "IServiceCollection. This is most likely because {2} was overridden by you or a " +
                              "third-party library. Make sure that you use the AddSingleton overload that takes " +
                              "in an existing instance—i.e. call " +
                              "services.AddSingleton<{2}>(new {2}()).",
                              typeof(ApplicationPartManager).FullName,
                              methodName,
                              typeof(ApplicationPartManager).Name));
            }
            else
            {
                return((ApplicationPartManager)descriptor.ImplementationInstance);
            }
        }
        /// <summary>
        /// Updates lifetime of <see cref="IExceptionMapper"/> service.
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <param name="lifetime">The new lifetime of <see cref="IExceptionMapper"/> service.</param>
        public static ExceptionMappingBuilder SetMapperLifetime(
            this ExceptionMappingBuilder builder,
            ServiceLifetime lifetime)
        {
            var serviceDescriptor = builder.Services.FirstOrDefault(
                sd => sd.ServiceType == typeof(IExceptionMapper));

            if (serviceDescriptor == null)
            {
                throw new InvalidOperationException("No registered 'IExceptionMapper' found.");
            }

            if (serviceDescriptor.Lifetime == lifetime ||
                serviceDescriptor.ImplementationInstance != null)
            {
                return(builder);
            }

            ServiceDescriptor?newServiceDescriptor = null;

            if (serviceDescriptor.ImplementationType != null)
            {
                newServiceDescriptor = new ServiceDescriptor(typeof(IExceptionMapper),
                                                             serviceDescriptor.ImplementationType, lifetime);
            }
            else if (serviceDescriptor.ImplementationFactory != null)
            {
                newServiceDescriptor = new ServiceDescriptor(typeof(IExceptionMapper),
                                                             serviceDescriptor.ImplementationFactory, lifetime);
            }

            if (newServiceDescriptor != null)
            {
                builder.Services.Replace(newServiceDescriptor);
            }

            return(builder);
        }
        /// <summary>
        /// Removes the first service in <see cref="IServiceCollection"/> with the same service type
        /// as <paramref name="descriptor"/> and adds <paramref name="descriptor"/> to the collection.
        /// </summary>
        /// <param name="collection">The <see cref="IServiceCollection"/>.</param>
        /// <param name="descriptor">The <see cref="ServiceDescriptor"/> to replace with.</param>
        /// <returns>The <see cref="IServiceCollection"/> for chaining.</returns>
        public static IServiceCollection Replace(
            this IServiceCollection collection,
            ServiceDescriptor descriptor)
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }

            if (descriptor == null)
            {
                throw new ArgumentNullException(nameof(descriptor));
            }

            ServiceDescriptor?registeredServiceDescriptor = collection.FirstOrDefault(s => s.ServiceType == descriptor.ServiceType);

            if (registeredServiceDescriptor != null)
            {
                collection.Remove(registeredServiceDescriptor);
            }

            collection.Add(descriptor);
            return(collection);
        }
 private static bool TryGetRuleEngineServiceDescriptor(Type type, out ServiceDescriptor?serviceDescriptor)
 {
 protected bool TryAddService(Type serviceType, Func <IServiceProvider, object> factory, ServiceLifetime lifetime, out ServiceDescriptor?addedDescriptor)
        protected bool TryAddService(Type serviceType, Func <IServiceProvider, object> factory, ServiceLifetime lifetime, [NotNullWhen(true)] out ServiceDescriptor?addedDescriptor)
#endif
        {
            ServiceDescriptor descriptor = new(serviceType, factory, lifetime);

            return(TryAddService(descriptor, out addedDescriptor));
        }
 protected bool TryAddService(Type serviceType, object implementationInstance, out ServiceDescriptor?addedDescriptor)
Beispiel #20
0
 public StoreBuilder <TState> UseJournaler <TActionJournaler>(TActionJournaler journaler)
     where TActionJournaler : IActionJournaler
 {
     _journallerDescriptor = this.ToServiceDescriptor <IActionJournaler, TActionJournaler>(journaler);
     return(this);
 }
Beispiel #21
0
 public StoreBuilder <TState> RemoveCurrentThreadScheduler()
 {
     _schedulerDescriptor = null;
     return(this);
 }
Beispiel #22
0
 public StoreBuilder <TState> UseScheduler(IScheduler scheduler)
 {
     _schedulerDescriptor = new ServiceDescriptor(typeof(IScheduler), scheduler);
     return(this);
 }
 protected bool TryAddService(ServiceDescriptor descriptor, out ServiceDescriptor?addedDescriptor)
 protected bool TryAddService(Type serviceType, Type implementationType, ServiceLifetime lifetime, out ServiceDescriptor?addedDescriptor)
        protected bool TryAddService(Type serviceType, object implementationInstance, [NotNullWhen(true)] out ServiceDescriptor?addedDescriptor)
#endif
        {
            ServiceDescriptor descriptor = new(serviceType, implementationInstance);

            return(TryAddService(descriptor, out addedDescriptor));
        }
Beispiel #26
0
        // ReSharper disable once InconsistentNaming
        /// <summary>
        /// Runs the wrapper.
        /// </summary>
        /// <param name="_args">Arguments. If empty, WinSW will behave in the service mode. Otherwise - CLI mode</param>
        /// <param name="descriptor">Service descriptor. If null, it will be initialized within the method.
        ///                          In such case configs will be loaded from the XML Configuration File.</param>
        /// <exception cref="Exception">Any unhandled exception</exception>
        public static void Run(string[] _args, ServiceDescriptor?descriptor = null)
        {
            bool isCLIMode = _args.Length > 0;

            // If descriptor is not specified, initialize the new one (and load configs from there)
            var d = descriptor ?? new ServiceDescriptor();

            // Configure the wrapper-internal logging.
            // STDIN and STDOUT of the child process will be handled independently.
            InitLoggers(d, isCLIMode);

            if (isCLIMode) // CLI mode, in-service mode otherwise
            {
                Log.Debug("Starting ServiceWrapper in the CLI mode");

                // Get service info for the future use
                Win32Services svc = new WmiRoot().GetCollection <Win32Services>();
                Win32Service  s   = svc.Select(d.Id);

                var args = new List <string>(Array.AsReadOnly(_args));
                if (args[0] == "/redirect")
                {
                    // Redirect output
                    // One might ask why we support this when the caller
                    // can redirect the output easily. The answer is for supporting UAC.
                    // On UAC-enabled Windows such as Vista, SCM operation requires
                    // elevated privileges, thus winsw.exe needs to be launched
                    // accordingly. This in turn limits what the caller can do,
                    // and among other things it makes it difficult for the caller
                    // to read stdout/stderr. Thus redirection becomes handy.
                    var f = new FileStream(args[1], FileMode.Create);
                    var w = new StreamWriter(f)
                    {
                        AutoFlush = true
                    };
                    Console.SetOut(w);
                    Console.SetError(w);

                    var handle = f.SafeFileHandle;
                    Kernel32.SetStdHandle(-11, handle); // set stdout
                    Kernel32.SetStdHandle(-12, handle); // set stder

                    args = args.GetRange(2, args.Count - 2);
                }

                args[0] = args[0].ToLower();
                if (args[0] == "install")
                {
                    Log.Info("Installing the service with id '" + d.Id + "'");

                    // Check if the service exists
                    if (s != null)
                    {
                        Console.WriteLine("Service with id '" + d.Id + "' already exists");
                        Console.WriteLine("To install the service, delete the existing one or change service Id in the configuration file");
                        throw new Exception("Installation failure: Service with id '" + d.Id + "' already exists");
                    }

                    string?username = null;
                    string?password = null;
                    bool   setallowlogonasaserviceright = false; // This variable is very readable.
                    if (args.Count > 1 && args[1] == "/p")
                    {
                        // we expected username/password on stdin
                        Console.Write("Username: "******"Password: "******"Set Account rights to allow log on as a service (y/n)?: ");
                        var keypressed = Console.ReadKey();
                        Console.WriteLine();
                        if (keypressed.Key == ConsoleKey.Y)
                        {
                            setallowlogonasaserviceright = true;
                        }
                    }
                    else
                    {
                        if (d.HasServiceAccount())
                        {
                            username = d.ServiceAccountUser;
                            password = d.ServiceAccountPassword;
                            setallowlogonasaserviceright = d.AllowServiceAcountLogonRight;
                        }
                    }

                    if (setallowlogonasaserviceright)
                    {
                        LogonAsAService.AddLogonAsAServiceRight(username !);
                    }

                    svc.Create(
                        d.Id,
                        d.Caption,
                        "\"" + d.ExecutablePath + "\"",
                        ServiceType.OwnProcess,
                        ErrorControl.UserNotified,
                        d.StartMode,
                        d.Interactive,
                        username,
                        password,
                        d.ServiceDependencies);

                    // update the description

                    /* Somehow this doesn't work, even though it doesn't report an error
                     * Win32Service s = svc.Select(d.Id);
                     * s.Description = d.Description;
                     * s.Commit();
                     */

                    // so using a classic method to set the description. Ugly.
                    Registry.LocalMachine.OpenSubKey("System").OpenSubKey("CurrentControlSet").OpenSubKey("Services")
                    .OpenSubKey(d.Id, true).SetValue("Description", d.Description);

                    var actions            = d.FailureActions;
                    var isDelayedAutoStart = d.StartMode == StartMode.Automatic && d.DelayedAutoStart;
                    if (actions.Count > 0 || isDelayedAutoStart)
                    {
                        using (ServiceManager scm = new ServiceManager())
                        {
                            using (Service sc = scm.Open(d.Id))
                            {
                                // Delayed auto start
                                if (isDelayedAutoStart)
                                {
                                    sc.SetDelayedAutoStart(true);
                                }

                                // Set the failure actions
                                if (actions.Count > 0)
                                {
                                    sc.ChangeConfig(d.ResetFailureAfter, actions);
                                }
                            }
                        }
                    }

                    return;
                }

                if (args[0] == "uninstall")
                {
                    Log.Info("Uninstalling the service with id '" + d.Id + "'");
                    if (s == null)
                    {
                        Log.Warn("The service with id '" + d.Id + "' does not exist. Nothing to uninstall");
                        return; // there's no such service, so consider it already uninstalled
                    }

                    if (s.Started)
                    {
                        // We could fail the opeartion here, but it would be an incompatible change.
                        // So it is just a warning
                        Log.Warn("The service with id '" + d.Id + "' is running. It may be impossible to uninstall it");
                    }

                    try
                    {
                        s.Delete();
                    }
                    catch (WmiException e)
                    {
                        if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                        {
                            Log.Error("Failed to uninstall the service with id '" + d.Id + "'"
                                      + ". It has been marked for deletion.");

                            // TODO: change the default behavior to Error?
                            return; // it's already uninstalled, so consider it a success
                        }
                        else
                        {
                            Log.Fatal("Failed to uninstall the service with id '" + d.Id + "'. WMI Error code is '" + e.ErrorCode + "'");
                        }

                        throw e;
                    }

                    return;
                }

                if (args[0] == "start")
                {
                    Log.Info("Starting the service with id '" + d.Id + "'");
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }

                    s.StartService();
                    return;
                }

                if (args[0] == "stop")
                {
                    Log.Info("Stopping the service with id '" + d.Id + "'");
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }

                    s.StopService();
                    return;
                }

                if (args[0] == "restart")
                {
                    Log.Info("Restarting the service with id '" + d.Id + "'");
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }

                    if (s.Started)
                    {
                        s.StopService();
                    }

                    while (s.Started)
                    {
                        Thread.Sleep(1000);
                        s = svc.Select(d.Id);
                    }

                    s.StartService();
                    return;
                }

                if (args[0] == "restart!")
                {
                    Log.Info("Restarting the service with id '" + d.Id + "'");

                    // run restart from another process group. see README.md for why this is useful.

                    STARTUPINFO si     = default;
                    bool        result = Kernel32.CreateProcess(null, d.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200 /*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out _);
                    if (!result)
                    {
                        throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
                    }

                    return;
                }

                if (args[0] == "status")
                {
                    Log.Debug("User requested the status of the process with id '" + d.Id + "'");
                    if (s == null)
                    {
                        Console.WriteLine("NonExistent");
                    }
                    else if (s.Started)
                    {
                        Console.WriteLine("Started");
                    }
                    else
                    {
                        Console.WriteLine("Stopped");
                    }

                    return;
                }

                if (args[0] == "test")
                {
                    WrapperService wsvc = new WrapperService(d);
                    wsvc.OnStart(args.ToArray());
                    Thread.Sleep(1000);
                    wsvc.OnStop();
                    return;
                }

                if (args[0] == "testwait")
                {
                    WrapperService wsvc = new WrapperService(d);
                    wsvc.OnStart(args.ToArray());
                    Console.WriteLine("Press any key to stop the service...");
                    Console.Read();
                    wsvc.OnStop();
                    return;
                }

                if (args[0] == "help" || args[0] == "--help" || args[0] == "-h" ||
                    args[0] == "-?" || args[0] == "/?")
                {
                    printHelp();
                    return;
                }

                if (args[0] == "version")
                {
                    printVersion();
                    return;
                }

                Console.WriteLine("Unknown command: " + args[0]);
                printAvailableCommandsInfo();
                throw new Exception("Unknown command: " + args[0]);
            }
            else
            {
                Log.Info("Starting ServiceWrapper in the service mode");
            }

            Run(new WrapperService(d));
        }
Beispiel #27
0
        // ReSharper disable once InconsistentNaming
        /// <summary>
        /// Runs the wrapper.
        /// </summary>
        /// <param name="_args">Arguments.</param>
        /// <param name="descriptor">Service descriptor. If null, it will be initialized within the method.
        ///                          In such case configs will be loaded from the XML Configuration File.</param>
        /// <exception cref="Exception">Any unhandled exception</exception>
        public static void Run(string[] _args, ServiceDescriptor?descriptor = null)
        {
            bool inCliMode = _args.Length > 0;

            // If descriptor is not specified, initialize the new one (and load configs from there)
            descriptor ??= new ServiceDescriptor();

            // Configure the wrapper-internal logging.
            // STDIN and STDOUT of the child process will be handled independently.
            InitLoggers(descriptor, inCliMode);

            if (!inCliMode)
            {
                Log.Debug("Starting WinSW in the service mode");
                Run(new WrapperService(descriptor));
                return;
            }

            Log.Debug("Starting WinSW in the CLI mode");

            if (_args.Length == 0)
            {
                printHelp();
                return;
            }

            // Get service info for the future use
            Win32Services svc = new WmiRoot().GetCollection <Win32Services>();
            Win32Service? s   = svc.Select(descriptor.Id);

            var args = new List <string>(Array.AsReadOnly(_args));

            if (args[0] == "/redirect")
            {
                // Redirect output
                // One might ask why we support this when the caller
                // can redirect the output easily. The answer is for supporting UAC.
                // On UAC-enabled Windows such as Vista, SCM operation requires
                // elevated privileges, thus winsw.exe needs to be launched
                // accordingly. This in turn limits what the caller can do,
                // and among other things it makes it difficult for the caller
                // to read stdout/stderr. Thus redirection becomes handy.
                var f = new FileStream(args[1], FileMode.Create);
                var w = new StreamWriter(f)
                {
                    AutoFlush = true
                };
                Console.SetOut(w);
                Console.SetError(w);

                var handle = f.SafeFileHandle;
                Kernel32.SetStdHandle(-11, handle); // set stdout
                Kernel32.SetStdHandle(-12, handle); // set stder

                args = args.GetRange(2, args.Count - 2);
            }

            args[0] = args[0].ToLower();
            if (args[0] == "install")
            {
                Log.Info("Installing the service with id '" + descriptor.Id + "'");

                // Check if the service exists
                if (s != null)
                {
                    Console.WriteLine("Service with id '" + descriptor.Id + "' already exists");
                    Console.WriteLine("To install the service, delete the existing one or change service Id in the configuration file");
                    throw new Exception("Installation failure: Service with id '" + descriptor.Id + "' already exists");
                }

                string?username = null;
                string?password = null;
                bool   setallowlogonasaserviceright = false; // This variable is very readable.
                if (args.Count > 1 && args[1] == "/p")
                {
                    // we expected username/password on stdin
                    Console.Write("Username: "******"Password: "******"Set Account rights to allow log on as a service (y/n)?: ");
                    var keypressed = Console.ReadKey();
                    Console.WriteLine();
                    if (keypressed.Key == ConsoleKey.Y)
                    {
                        setallowlogonasaserviceright = true;
                    }
                }
                else
                {
                    if (descriptor.HasServiceAccount())
                    {
                        username = descriptor.ServiceAccountUser;
                        password = descriptor.ServiceAccountPassword;
                        setallowlogonasaserviceright = descriptor.AllowServiceAcountLogonRight;
                    }
                }

                if (setallowlogonasaserviceright)
                {
                    LogonAsAService.AddLogonAsAServiceRight(username !);
                }

                svc.Create(
                    descriptor.Id,
                    descriptor.Caption,
                    "\"" + descriptor.ExecutablePath + "\"",
                    ServiceType.OwnProcess,
                    ErrorControl.UserNotified,
                    descriptor.StartMode.ToString(),
                    descriptor.Interactive,
                    username,
                    password,
                    descriptor.ServiceDependencies);

                using ServiceManager scm = new ServiceManager();
                using Service sc         = scm.Open(descriptor.Id);

                sc.SetDescription(descriptor.Description);

                var actions = descriptor.FailureActions;
                if (actions.Count > 0)
                {
                    sc.SetFailureActions(descriptor.ResetFailureAfter, actions);
                }

                var isDelayedAutoStart = descriptor.StartMode == StartMode.Automatic && descriptor.DelayedAutoStart;
                if (isDelayedAutoStart)
                {
                    sc.SetDelayedAutoStart(true);
                }

                if (descriptor.SecurityDescriptor != null)
                {
                    // throws ArgumentException
                    RawSecurityDescriptor rawSecurityDescriptor = new RawSecurityDescriptor(descriptor.SecurityDescriptor);
                    byte[] securityDescriptorBytes = new byte[rawSecurityDescriptor.BinaryLength];
                    rawSecurityDescriptor.GetBinaryForm(securityDescriptorBytes, 0);
                    _ = Advapi32.SetServiceObjectSecurity(sc.Handle, SecurityInfos.DiscretionaryAcl, securityDescriptorBytes);
                }

                return;
            }

            if (args[0] == "uninstall")
            {
                Log.Info("Uninstalling the service with id '" + descriptor.Id + "'");
                if (s is null)
                {
                    Log.Warn("The service with id '" + descriptor.Id + "' does not exist. Nothing to uninstall");
                    return; // there's no such service, so consider it already uninstalled
                }

                if (s.Started)
                {
                    // We could fail the opeartion here, but it would be an incompatible change.
                    // So it is just a warning
                    Log.Warn("The service with id '" + descriptor.Id + "' is running. It may be impossible to uninstall it");
                }

                try
                {
                    s.Delete();
                }
                catch (WmiException e)
                {
                    if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                    {
                        Log.Error("Failed to uninstall the service with id '" + descriptor.Id + "'"
                                  + ". It has been marked for deletion.");

                        // TODO: change the default behavior to Error?
                        return; // it's already uninstalled, so consider it a success
                    }
                    else
                    {
                        Log.Fatal("Failed to uninstall the service with id '" + descriptor.Id + "'. WMI Error code is '" + e.ErrorCode + "'");
                    }

                    throw e;
                }

                return;
            }

            if (args[0] == "start")
            {
                Log.Info("Starting the service with id '" + descriptor.Id + "'");
                if (s is null)
                {
                    ThrowNoSuchService();
                }

                try
                {
                    s.StartService();
                }
                catch (WmiException e)
                {
                    if (e.ErrorCode == ReturnValue.ServiceAlreadyRunning)
                    {
                        Log.Info($"The service with ID '{descriptor.Id}' has already been started");
                    }
                    else
                    {
                        throw;
                    }
                }

                return;
            }

            if (args[0] == "stop")
            {
                Log.Info("Stopping the service with id '" + descriptor.Id + "'");
                if (s is null)
                {
                    ThrowNoSuchService();
                }

                try
                {
                    s.StopService();
                }
                catch (WmiException e)
                {
                    if (e.ErrorCode == ReturnValue.ServiceCannotAcceptControl)
                    {
                        Log.Info($"The service with ID '{descriptor.Id}' is not running");
                    }
                    else
                    {
                        throw;
                    }
                }

                return;
            }

            if (args[0] == "restart")
            {
                Log.Info("Restarting the service with id '" + descriptor.Id + "'");
                if (s is null)
                {
                    ThrowNoSuchService();
                }

                if (s.Started)
                {
                    s.StopService();
                }

                while (s.Started)
                {
                    Thread.Sleep(1000);
                    s = svc.Select(descriptor.Id) !;
                }

                s.StartService();
                return;
            }

            if (args[0] == "restart!")
            {
                Log.Info("Restarting the service with id '" + descriptor.Id + "'");

                // run restart from another process group. see README.md for why this is useful.

                bool result = Kernel32.CreateProcess(null, descriptor.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, Kernel32.CREATE_NEW_PROCESS_GROUP, IntPtr.Zero, null, default, out _);
Beispiel #28
0
 private void InitialDispatcher()
 {
     this.UseDefaultDispatcher();
     this.UseNoJournaler();
     _schedulerDescriptor = this.ToServiceDescriptor <IScheduler, CurrentThreadScheduler>(Scheduler.CurrentThread);
 }
Beispiel #29
0
 public StoreBuilder <TState> UseDispatcher <TDispatcher>(TDispatcher dispatcher)
     where TDispatcher : IActionDispatcher
 {
     _actionDispatcherDescriptor = this.ToServiceDescriptor <IActionDispatcher, TDispatcher>(dispatcher);
     return(this);
 }
        protected bool TryAddService(Type serviceType, Type implementationType, ServiceLifetime lifetime, [NotNullWhen(true)] out ServiceDescriptor?addedDescriptor)
#endif
        {
            ServiceDescriptor descriptor = new(serviceType, implementationType, lifetime);

            return(TryAddService(descriptor, out addedDescriptor));
        }