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") { 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 (Advapi32.ServiceManager scm = new Advapi32.ServiceManager()) { using (Advapi32.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] == "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()); }
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") { 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 (Advapi32.ServiceManager scm = new Advapi32.ServiceManager()) { using (Advapi32.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] == "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()); }