Пример #1
0
        public static void Run(string[] _args)
        {
            if (_args.Length > 0)
            {
                var           d   = new ServiceDescriptor();
                Win32Services svc = new WmiRoot().GetCollection <Win32Services>();
                Console.WriteLine("Looking for service...");
                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);
                    w.AutoFlush = true;
                    Console.SetOut(w);
                    Console.SetError(w);

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

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

                args[0] = args[0].ToLower();
                if (args[0] == "install")
                {
                    svc.Create(
                        d.Id,
                        d.Caption,
                        "\"" + ServiceDescriptor.ExecutablePath + "\"",
                        WMI.ServiceType.OwnProcess,
                        ErrorControl.UserNotified,
                        StartMode.Automatic,
                        d.Interactive,
                        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);
                    Console.WriteLine("Installed");
                }
                if (args[0] == "uninstall")
                {
                    if (s == null)
                    {
                        return; // there's no such service, so consider it already uninstalled
                    }
                    try
                    {
                        s.Delete();
                    }
                    catch (WmiException e)
                    {
                        if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                        {
                            return; // it's already uninstalled, so consider it a success
                        }
                        throw e;
                    }
                    Console.WriteLine("Uninstalled");
                }
                if (args[0] == "start")
                {
                    Console.WriteLine("Requesting start");
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }
                    s.StartService();
                }
                if (args[0] == "stop")
                {
                    Console.WriteLine("Requesting stop");
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }
                    if (s.Started)
                    {
                        s.StopService();
                        Console.WriteLine("Stopped.");
                    }
                    else
                    {
                        Console.WriteLine("Not running.");
                    }
                }
                if (args[0] == "restart")
                {
                    Console.WriteLine("Requesting restart");
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }

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

                    while (s.Started)
                    {
                        // XXX:  Should give up after a while, and display error-message.
                        Thread.Sleep(1000);
                        s = svc.Select(d.Id);
                    }

                    s.StartService();
                }
                if (args[0] == "status")
                {
                    if (s == null)
                    {
                        Console.WriteLine("NonExistent");
                    }
                    else if (s.Started)
                    {
                        Console.WriteLine("Started");
                    }
                    else
                    {
                        Console.WriteLine("Stopped");
                    }
                }
                if (args[0] == "test")
                {
                    WrapperService wsvc = new WrapperService();
                    wsvc.OnStart(args.ToArray());
                    Thread.Sleep(1000);
                    wsvc.OnStop();
                }
                if (args[0] == "version")
                {
                    Version version = new Version();
                    Console.WriteLine("Compiled on " + version.version);
                }
                if (args[0] == "specs")
                {
                    Dictionary <string, string> specs = new Dictionary <string, string>()
                    {
                        { "argument", d.Arguments },
                        { "beeponshutdown", d.BeepOnShutdown.ToString() },
                        { "name", d.Caption },
                        { "description", d.Description },
                        { "executable", d.Executable },
                        { "startargument", d.Startarguments },
                        { "stopexecutable", d.StopExecutable },
                        { "stopargument", d.Stoparguments },
                        { "id", d.Id },
                        { "interactive", d.Interactive.ToString() },
                        { "logpath", d.LogDirectory },
                        { "sleeptime", d.SleepTime.ToString() },
                        { "waithint", d.WaitHint.ToString() },
                    };

                    foreach (KeyValuePair <string, string> spec in specs)
                    {
                        Console.WriteLine(spec.Key + ":  " + spec.Value);
                    }

                    Console.WriteLine("env:");
                    foreach (var k in d.EnvironmentVariables)
                    {
                        Console.WriteLine("\t" + k.Key + "=" + k.Value);
                    }

                    Console.WriteLine("downloads:");
                    foreach (var k in d.Downloads)
                    {
                        Console.WriteLine("\tFrom:  " + k.From + "\tTo:  " + k.To);
                    }

                    Console.WriteLine("depend:");
                    foreach (var k in d.ServiceDependencies)
                    {
                        Console.WriteLine("\t" + k);
                    }

                    Console.WriteLine("log:");
                    Console.WriteLine("\tmode:  " + d.LogHandler.logmode());
                    if (d.LogHandler.GetType() == typeof(TimeBasedRollingLogAppender))
                    {
                        Console.WriteLine("\tpattern:  " + ((TimeBasedRollingLogAppender)d.LogHandler).Pattern);
                        Console.WriteLine("\tperiod:  " + ((TimeBasedRollingLogAppender)d.LogHandler).Period);
                    }
                    else if (d.LogHandler.GetType() == typeof(SizeBasedRollingLogAppender))
                    {
                        Console.WriteLine("\tkeepFiles:  " + ((SizeBasedRollingLogAppender)d.LogHandler).FilesToKeep);
                        Console.WriteLine("\tsizeThreshold:  " + ((SizeBasedRollingLogAppender)d.LogHandler).SizeThreshold);
                    }
                }
                return;
            }
            ServiceBase.Run(new WrapperService());
        }
Пример #2
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, password = null;
                    bool   setallowlogonasaserviceright = false;
                    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 = new STARTUPINFO();
                    PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

                    bool result = Kernel32.CreateProcess(null, d.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200 /*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out pi);
                    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));
        }
Пример #3
0
        public static void Run(string[] args)
        {
            if (args.Length > 0) {
            var d = new ServiceDescriptor();
            Win32Services svc = new WmiRoot().GetCollection<Win32Services>();
            Win32Service s = svc.Select(d.Id);

            args[0] = args[0].ToLower();
            if (args[0] == "install") {
              svc.Create(
              d.Id,
              d.Caption,
              "\"" + ServiceDescriptor.ExecutablePath + "\"",
              WMI.ServiceType.OwnProcess,
              ErrorControl.UserNotified,
              StartMode.Automatic,
              d.Interactive,
              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);
            }
            if (args[0] == "uninstall") {
              if (s == null)
            return; // there's no such service, so consider it already uninstalled
              try {
            s.Delete();
              }
              catch (WmiException e) {
            if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
              return; // it's already uninstalled, so consider it a success
            throw e;
              }
            }
            if (args[0] == "start") {
              if (s == null) ThrowNoSuchService();
              s.StartService();
            }
            if (args[0] == "stop") {
              if (s == null) ThrowNoSuchService();
              s.StopService();
            }
            if (args[0] == "restart") {
              if (s == null)
            ThrowNoSuchService();

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

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

              s.StartService();
            }
            if (args[0] == "status") {
              if (s == null)
            Console.WriteLine("NonExistent");
              else if (s.Started)
            Console.WriteLine("Started");
              else
            Console.WriteLine("Stopped");
            }
            if (args[0] == "test") {
              WrapperService wsvc = new WrapperService();
              wsvc.OnStart(args);
              Thread.Sleep(1000);
              wsvc.OnStop();
            }
            return;
              }
              ServiceBase.Run(new WrapperService());
        }
Пример #4
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 _);
Пример #5
0
        public static void Run(string[] argsArray, IWinSWConfiguration?descriptor = null)
        {
            bool inConsoleMode = argsArray.Length > 0;

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

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

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

            Log.Debug("Starting WinSW in console mode");

            if (argsArray.Length == 0)
            {
                PrintHelp();
                return;
            }

            // Get service info for the future use
            IWin32Services svcs = new WmiRoot().GetCollection <IWin32Services>();
            IWin32Service? svc  = svcs.Select(descriptor.Id);

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

            if (args[0] == "/redirect")
            {
                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);
            }

            bool elevated;

            if (args[0] == "/elevated")
            {
                elevated = true;

                _ = ConsoleApis.FreeConsole();
                _ = ConsoleApis.AttachConsole(ConsoleApis.ATTACH_PARENT_PROCESS);

                args = args.GetRange(1, args.Count - 1);
            }
            else if (Environment.OSVersion.Version.Major == 5)
            {
                // Windows XP
                elevated = true;
            }
            else
            {
                elevated = IsProcessElevated();
            }

            switch (args[0].ToLower())
            {
            case "install":
                Install();
                return;

            case "uninstall":
                Uninstall();
                return;

            case "start":
                Start();
                return;

            case "stop":
                Stop();
                return;

            case "stopwait":
                StopWait();
                return;

            case "restart":
                Restart();
                return;

            case "restart!":
                RestartSelf();
                return;

            case "status":
                Status();
                return;

            case "test":
                Test();
                return;

            case "testwait":
                TestWait();
                return;

            case "help":
            case "--help":
            case "-h":
            case "-?":
            case "/?":
                PrintHelp();
                return;

            case "version":
                PrintVersion();
                return;

            default:
                Console.WriteLine("Unknown command: " + args[0]);
                PrintAvailableCommands();
#pragma warning disable S112 // General exceptions should never be thrown
                throw new Exception("Unknown command: " + args[0]);
#pragma warning restore S112 // General exceptions should never be thrown
            }

            void Install()
            {
                if (!elevated)
                {
                    Elevate();
                    return;
                }

                Log.Info("Installing the service with id '" + descriptor.Id + "'");

                // Check if the service exists
                if (svc != 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");
#pragma warning disable S112 // General exceptions should never be thrown
                    throw new Exception("Installation failure: Service with id '" + descriptor.Id + "' already exists");
#pragma warning restore S112 // General exceptions should never be thrown
                }

                string?username = null;
                string?password = null;
                bool   allowServiceLogonRight = false;
                if (args.Count > 1 && args[1] == "/p")
                {
                    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)
                    {
                        allowServiceLogonRight = true;
                    }
                }
                else
                {
                    if (descriptor.ServiceAccount.HasServiceAccount())
                    {
                        username = descriptor.ServiceAccount.ServiceAccountUser;
                        password = descriptor.ServiceAccount.ServiceAccountPassword;
                        allowServiceLogonRight = descriptor.ServiceAccount.AllowServiceAcountLogonRight;
                    }
                }

                if (allowServiceLogonRight)
                {
                    Security.AddServiceLogonRight(descriptor.ServiceAccount.ServiceAccountDomain !, descriptor.ServiceAccount.ServiceAccountName !);
                }

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

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

                sc.SetDescription(descriptor.Description);

                SC_ACTION[] actions = descriptor.FailureActions;
                if (actions.Length > 0)
                {
                    sc.SetFailureActions(descriptor.ResetFailureAfter, actions);
                }

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

                string?securityDescriptor = descriptor.SecurityDescriptor;
                if (securityDescriptor != null)
                {
                    // throws ArgumentException
                    sc.SetSecurityDescriptor(new RawSecurityDescriptor(securityDescriptor));
                }

                string eventLogSource = descriptor.Id;
                if (!EventLog.SourceExists(eventLogSource))
                {
                    EventLog.CreateEventSource(eventLogSource, "Application");
                }
            }

            void Uninstall()
            {
                if (!elevated)
                {
                    Elevate();
                    return;
                }

                Log.Info("Uninstalling the service with id '" + descriptor.Id + "'");
                if (svc 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 (svc.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
                {
                    svc.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;
                }
            }

            void Start()
            {
                if (!elevated)
                {
                    Elevate();
                    return;
                }

                Log.Info("Starting the service with id '" + descriptor.Id + "'");
                if (svc is null)
                {
                    ThrowNoSuchService();
                }

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

            void Stop()
            {
                if (!elevated)
                {
                    Elevate();
                    return;
                }

                Log.Info("Stopping the service with id '" + descriptor.Id + "'");
                if (svc is null)
                {
                    ThrowNoSuchService();
                }

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

            void StopWait()
            {
                if (!elevated)
                {
                    Elevate();
                    return;
                }

                Log.Info("Stopping the service with id '" + descriptor.Id + "'");
                if (svc is null)
                {
                    ThrowNoSuchService();
                }

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

                while (svc != null && svc.Started)
                {
                    Log.Info("Waiting the service to stop...");
                    Thread.Sleep(1000);
                    svc = svcs.Select(descriptor.Id);
                }

                Log.Info("The service stopped.");
            }

            void Restart()
            {
                if (!elevated)
                {
                    Elevate();
                    return;
                }

                Log.Info("Restarting the service with id '" + descriptor.Id + "'");
                if (svc is null)
                {
                    ThrowNoSuchService();
                }

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

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

                svc.StartService();
            }

            void RestartSelf()
            {
                if (!elevated)
                {
                    throw new UnauthorizedAccessException("Access is denied.");
                }

                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 = ProcessApis.CreateProcess(null, descriptor.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, ProcessApis.CREATE_NEW_PROCESS_GROUP, IntPtr.Zero, null, default, out _);
Пример #6
0
        public static void Run(string[] _args)
        {
            if (_args.Length > 0)
            {
                var d = new ServiceDescriptor();
                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);
                    w.AutoFlush = true;
                    Console.SetOut(w);
                    Console.SetError(w);

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

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

                args[0] = args[0].ToLower();
                if (args[0] == "install")
                {
                    svc.Create(
                        d.Id,
                        d.Caption,
                        "\""+ServiceDescriptor.ExecutablePath+"\"",
                        WMI.ServiceType.OwnProcess,
                        ErrorControl.UserNotified,
                        StartMode.Automatic,
                        d.Interactive,
                        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);
                }
                if (args[0] == "uninstall")
                {
                    if (s == null)
                        return; // there's no such service, so consider it already uninstalled
                    try
                    {
                        s.Delete();
                    }
                    catch (WmiException e)
                    {
                        if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                            return; // it's already uninstalled, so consider it a success
                        throw e;
                    }
                }
                if (args[0] == "start")
                {
                    if (s == null) ThrowNoSuchService();
                    s.StartService();
                }
                if (args[0] == "stop")
                {
                    if (s == null) ThrowNoSuchService();
                    s.StopService();
                }
                if (args[0] == "restart")
                {
                    if (s == null)
                        ThrowNoSuchService();

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

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

                    s.StartService();
                }
                if (args[0] == "status")
                {
                    if (s == null)
                        Console.WriteLine("NonExistent");
                    else if (s.Started)
                        Console.WriteLine("Started");
                    else
                        Console.WriteLine("Stopped");
                }
                if (args[0] == "test")
                {
                    WrapperService wsvc = new WrapperService();
                    wsvc.OnStart(args.ToArray());
                    Thread.Sleep(1000);
                    wsvc.OnStop();
                }
                return;
            }
            ServiceBase.Run(new WrapperService());
        }
Пример #7
0
        // ReSharper disable once InconsistentNaming
        public static void Run(string[] _args, ServiceDescriptor descriptor = null)
        {
            if (_args.Length > 0)
            {
                var d = descriptor ?? new ServiceDescriptor();
                var svc = new WmiRoot().GetCollection<Win32Services>();
                var 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.Handle;
                    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")
                {
                    // 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, password = null;
                    var setallowlogonasaserviceright = false;
                    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;
                    if (actions.Count > 0)
                    {
            // set the failure actions
                        using (var scm = new ServiceManager())
                        {
                            using (var sc = scm.Open(d.Id))
                            {
                                sc.ChangeConfig(d.ResetFailureAfter, actions);
                            }
                        }
                    }
                    return;
                }
                if (args[0] == "uninstall")
                {
                    if (s == null)
                    {
                        Console.WriteLine("Warning! The service with id '" + d.Id +
                                          "' does not exist. Nothing to uninstall");
                        return; // there's no such service, so consider it already uninstalled
                    }
                    try
                    {
                        s.Delete();
                    }
                    catch (WmiException e)
                    {
                        if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                            return; // it's already uninstalled, so consider it a success
                        throw e;
                    }
                    return;
                }
                if (args[0] == "start")
                {
                    if (s == null) ThrowNoSuchService();
                    s.StartService();
                    return;
                }
                if (args[0] == "stop")
                {
                    if (s == null) ThrowNoSuchService();
                    s.StopService();
                    return;
                }
                if (args[0] == "restart")
                {
                    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!")
                {
                    // run restart from another process group. see README.md for why this is useful.

                    var si = new STARTUPINFO();
                    var pi = new PROCESS_INFORMATION();

                    var result = Kernel32.CreateProcess(null, d.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero,
                        false, 0x200 /*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out pi);
                    if (!result)
                    {
                        throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
                    }
                    return;
                }
                if (args[0] == "status")
                {
                    if (s == null)
                        Console.WriteLine("NonExistent");
                    else if (s.Started)
                        Console.WriteLine("Started");
                    else
                        Console.WriteLine("Stopped");
                    return;
                }
                if (args[0] == "test")
                {
                    var wsvc = new WrapperService();
                    wsvc.OnStart(args.ToArray());
                    Thread.Sleep(1000);
                    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]);
            }
            Run(new WrapperService());
        }
Пример #8
0
        public static void Run(string[] _args)
        {
            if (_args.Length > 0)
            {
                var d = new ServiceDescriptor();
                Win32Services svc = new WmiRoot().GetCollection<Win32Services>();
                Console.WriteLine("Looking for service...");
                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);
                    w.AutoFlush = true;
                    Console.SetOut(w);
                    Console.SetError(w);

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

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

                args[0] = args[0].ToLower();
                if (args[0] == "install")
                {
                    svc.Create(
                        d.Id,
                        d.Caption,
                        "\""+ServiceDescriptor.ExecutablePath+"\"",
                        WMI.ServiceType.OwnProcess,
                        ErrorControl.UserNotified,
                        StartMode.Automatic,
                        d.Interactive,
                        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);
                    Console.WriteLine("Installed");
                }
                if (args[0] == "uninstall")
                {
                    if (s == null)
                        return; // there's no such service, so consider it already uninstalled
                    try
                    {
                        s.Delete();
                    }
                    catch (WmiException e)
                    {
                        if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                            return; // it's already uninstalled, so consider it a success
                        throw e;
                    }
                    Console.WriteLine("Uninstalled");
                }
                if (args[0] == "start")
                {
                    Console.WriteLine("Requesting start");
                    if (s == null) ThrowNoSuchService();
                    s.StartService();
                }
                if (args[0] == "stop")
                {
                    Console.WriteLine("Requesting stop");
                    if (s == null) ThrowNoSuchService();
                    if (s.Started)
                    {
                        s.StopService();
                        Console.WriteLine("Stopped.");
                    }
                    else
                    {
                        Console.WriteLine("Not running.");
                    }
                }
                if (args[0] == "restart")
                {
                    Console.WriteLine("Requesting restart");
                    if (s == null)
                        ThrowNoSuchService();

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

                    while (s.Started)
                    {

                        // XXX:  Should give up after a while, and display error-message.
                        Thread.Sleep(1000);
                        s = svc.Select(d.Id);
                    }

                    s.StartService();
                }
                if (args[0] == "status")
                {
                    if (s == null)
                        Console.WriteLine("NonExistent");
                    else if (s.Started)
                        Console.WriteLine("Started");
                    else
                        Console.WriteLine("Stopped");
                }
                if (args[0] == "test")
                {
                    WrapperService wsvc = new WrapperService();
                    wsvc.OnStart(args.ToArray());
                    Thread.Sleep(1000);
                    wsvc.OnStop();
                }
                if (args[0] == "version")
                {
                    Version version = new Version();
                    Console.WriteLine("Compiled on " + version.version);
                }
                if (args[0] == "specs")
                {
                    Dictionary<string, string> specs = new Dictionary<string, string>()
                    {
                        {"argument", d.Arguments},
                        {"beeponshutdown", d.BeepOnShutdown.ToString()},
                        {"name", d.Caption},
                        {"description", d.Description},
                        {"executable", d.Executable},
                        {"startargument", d.Startarguments},
                        {"stopexecutable", d.StopExecutable},
                        {"stopargument", d.Stoparguments},
                        {"id", d.Id},
                        {"interactive", d.Interactive.ToString()},
                        {"logpath", d.LogDirectory},
                        {"sleeptime", d.SleepTime.ToString()},
                        {"waithint", d.WaitHint.ToString()},
                    };

                    foreach (KeyValuePair<string, string> spec in specs)
                    {
                        Console.WriteLine(spec.Key + ":  " + spec.Value);
                    }

                    Console.WriteLine("env:");
                    foreach (var k in d.EnvironmentVariables)
                    {
                        Console.WriteLine("\t" + k.Key + "=" + k.Value);
                    }

                    Console.WriteLine("downloads:");
                    foreach (var k in d.Downloads)
                    {
                        Console.WriteLine("\tFrom:  " + k.From + "\tTo:  " + k.To);
                    }

                    Console.WriteLine("depend:");
                    foreach (var k in d.ServiceDependencies)
                    {
                        Console.WriteLine("\t" + k);
                    }

                    Console.WriteLine("log:");
                    Console.WriteLine("\tmode:  " + d.LogHandler.logmode());
                    if (d.LogHandler.GetType() == typeof(TimeBasedRollingLogAppender))
                    {
                        Console.WriteLine("\tpattern:  " + ((TimeBasedRollingLogAppender)d.LogHandler).Pattern);
                        Console.WriteLine("\tperiod:  " + ((TimeBasedRollingLogAppender)d.LogHandler).Period);
                    }
                    else if (d.LogHandler.GetType() == typeof(SizeBasedRollingLogAppender))
                    {
                        Console.WriteLine("\tkeepFiles:  " + ((SizeBasedRollingLogAppender)d.LogHandler).FilesToKeep);
                        Console.WriteLine("\tsizeThreshold:  " + ((SizeBasedRollingLogAppender)d.LogHandler).SizeThreshold);
                    }

                }
                return;
            }
            ServiceBase.Run(new WrapperService());
        }
Пример #9
0
        public static void Run(string[] _args)
        {
            if (_args.Length > 0)
            {
                var           d   = new ServiceDescriptor();
                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);
                    w.AutoFlush = true;
                    Console.SetOut(w);
                    Console.SetError(w);

                    var handle = f.Handle;
                    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")
                {
                    string username = null, password = null;
                    if (args.Count > 1 && args[1] == "/p")
                    {
                        // we expected username/password on stdin
                        Console.Write("Username: "******"Password: "******"\"" + d.ExecutablePath + "\"",
                        WMI.ServiceType.OwnProcess,
                        ErrorControl.UserNotified,
                        StartMode.Automatic,
                        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;
                    if (actions.Count > 0)
                    {// set the failure actions
                        using (ServiceManager scm = new ServiceManager())
                        {
                            using (Service sc = scm.Open(d.Id))
                            {
                                sc.ChangeConfig(d.ResetFailureAfter, actions);
                            }
                        }
                    }
                }
                if (args[0] == "uninstall")
                {
                    if (s == null)
                    {
                        return; // there's no such service, so consider it already uninstalled
                    }
                    try
                    {
                        s.Delete();
                    }
                    catch (WmiException e)
                    {
                        if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                        {
                            return; // it's already uninstalled, so consider it a success
                        }
                        throw e;
                    }
                }
                if (args[0] == "start")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }
                    s.StartService();
                }
                if (args[0] == "stop")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }
                    s.StopService();
                }
                if (args[0] == "restart")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }

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

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

                    s.StartService();
                }
                if (args[0] == "restart!")
                {
                    // run restart from another process group. see README.md for why this is useful.

                    STARTUPINFO         si = new STARTUPINFO();
                    PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

                    bool result = Kernel32.CreateProcess(null, d.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200 /*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out pi);
                    if (!result)
                    {
                        throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
                    }
                }
                if (args[0] == "status")
                {
                    if (s == null)
                    {
                        Console.WriteLine("NonExistent");
                    }
                    else if (s.Started)
                    {
                        Console.WriteLine("Started");
                    }
                    else
                    {
                        Console.WriteLine("Stopped");
                    }
                }
                if (args[0] == "test")
                {
                    WrapperService wsvc = new WrapperService();
                    wsvc.OnStart(args.ToArray());
                    Thread.Sleep(1000);
                    wsvc.OnStop();
                }
                return;
            }
            ServiceBase.Run(new WrapperService());
        }
Пример #10
0
        public static void Run(string[] args)
        {
            if (args.Length > 0)
            {
                var           d   = new ServiceDescriptor();
                Win32Services svc = new WmiRoot().GetCollection <Win32Services>();
                Win32Service  s   = svc.Select(d.Id);

                args[0] = args[0].ToLower();
                if (args[0] == "install")
                {
                    svc.Create(
                        d.Id,
                        d.Caption,
                        "\"" + ServiceDescriptor.ExecutablePath + "\"",
                        WMI.ServiceType.OwnProcess,
                        ErrorControl.UserNotified,
                        StartMode.Automatic,
                        d.Interactive,
                        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);
                }
                if (args[0] == "uninstall")
                {
                    if (s == null)
                    {
                        return; // there's no such service, so consider it already uninstalled
                    }
                    try {
                        s.Delete();
                    }
                    catch (WmiException e) {
                        if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                        {
                            return; // it's already uninstalled, so consider it a success
                        }
                        throw e;
                    }
                }
                if (args[0] == "start")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }
                    s.StartService();
                }
                if (args[0] == "stop")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }
                    s.StopService();
                }
                if (args[0] == "restart")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }

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

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

                    s.StartService();
                }
                if (args[0] == "status")
                {
                    if (s == null)
                    {
                        Console.WriteLine("NonExistent");
                    }
                    else if (s.Started)
                    {
                        Console.WriteLine("Started");
                    }
                    else
                    {
                        Console.WriteLine("Stopped");
                    }
                }
                if (args[0] == "test")
                {
                    WrapperService wsvc = new WrapperService();
                    wsvc.OnStart(args);
                    Thread.Sleep(1000);
                    wsvc.OnStop();
                }
                return;
            }
            ServiceBase.Run(new WrapperService());
        }
Пример #11
0
        public static void Run(string[] _args)
        {
            if (_args.Length > 0)
            {
                var           d   = new ServiceDescriptor();
                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);
                    w.AutoFlush = true;
                    Console.SetOut(w);
                    Console.SetError(w);

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

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

                args[0] = args[0].ToLower();
                if (args[0] == "install")
                {
                    svc.Create(
                        d.Id,
                        d.Caption,
                        "\"" + ServiceDescriptor.ExecutablePath + "\"",
                        WMI.ServiceType.OwnProcess,
                        ErrorControl.UserNotified,
                        StartMode.Automatic,
                        d.Interactive,
                        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);
                }
                if (args[0] == "uninstall")
                {
                    if (s == null)
                    {
                        return; // there's no such service, so consider it already uninstalled
                    }
                    try
                    {
                        s.Delete();
                    }
                    catch (WmiException e)
                    {
                        if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
                        {
                            return; // it's already uninstalled, so consider it a success
                        }
                        throw e;
                    }
                }
                if (args[0] == "start")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }
                    s.StartService();
                }
                if (args[0] == "stop")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }
                    s.StopService();
                }
                if (args[0] == "restart")
                {
                    if (s == null)
                    {
                        ThrowNoSuchService();
                    }

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

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

                    s.StartService();
                }
                if (args[0] == "status")
                {
                    if (s == null)
                    {
                        Console.WriteLine("NonExistent");
                    }
                    else if (s.Started)
                    {
                        Console.WriteLine("Started");
                    }
                    else
                    {
                        Console.WriteLine("Stopped");
                    }
                }
                if (args[0] == "test")
                {
                    WrapperService wsvc = new WrapperService();
                    wsvc.OnStart(args.ToArray());
                    Thread.Sleep(1000);
                    wsvc.OnStop();
                }
                return;
            }
            ServiceBase.Run(new WrapperService());
        }