如何从 Windows 服务运行控制台应用程序?

发布于 2024-08-03 20:48:17 字数 644 浏览 2 评论 0原文

我有一个用 C# 编写的 Windows 服务,我需要从中运行一个控制台应用程序。 控制台应用程序也是用 C# 编写的。

当控制台应用程序不是从 Windows 服务运行时,它运行良好。当它从 ws 运行时,它不会做任何它应该做的事情,因为它应该工作 10-20 秒,我在调试代码中看到立即执行。

我使用以下代码启动我的控制台应用程序:

proc.Start(fullPathToConsole, args);
proc.WaitForExit();

控制台的路径是正确的,当我尝试从 cmd 或仅在资源管理器(不带参数)中运行它时,它工作正常。但运行该服务后我没有看到任何效果。

我已经尝试转到服务属性并授予其访问桌面的权限并在系统和我的用户(也在服务属性中指定)下运行。一切都保持不变。

添加:我知道服务没有用户界面,但我不想要。我想要服务运行控制台应用程序。无需从中获取任何数据或使用此控制台(如 ui),只需运行它即可完成其工作。

更新我:发现运行 calc 或任何其他 Windows 应用程序很容易。但仍然无法运行 cmd 或任何控制台应用程序。实际上我需要在 XP SP2 和 Windows 2003 Server 上运行它。所以无论如何都不需要与 Vista 进行交互。

很高兴收到任何评论!

I have a windows service, written in c# and I need to run a console application from it.
Console application also written in c#.

Console application is running fine when it is run not from windows service. When it is ran from ws it doesn`t do anything it should and as it should work for 10-20 seconds I see in debug code is executed at once.

I`m starting my console app with the following code:

proc.Start(fullPathToConsole, args);
proc.WaitForExit();

the path to console is right and when I`m trying to run it from the cmd or just in explorer (without args) it works fine. But after running with the service I see no effect.

I already tried to go to service properties and give it access to desktop and run under both system and my user (also specified in service properties). All remains the same.

ADDITION: I know service do not have ui and I don't want one. I want service to run console application. No need to get any data from it or use this console like ui, just run it to do it`s job.

UPDATE I: discovered, that running calc or any other windows app is easy. But still can`t run cmd or any console app. Actually I need to run it on XP SP2 and Windows 2003 Server. So do not need to interact with Vista in anyway.

Would be glad to any comments!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

衣神在巴黎 2024-08-10 20:48:18

您的控制台应用程序需要用户交互吗?如果是这样,那就是严重的禁忌,您应该重新设计您的应用程序。虽然有一些技巧可以在旧版本的操作系统中实现这种功能,但这肯定会在未来被打破。

如果您的应用程序不需要用户交互,那么您的问题可能与服务运行时的用户有关。尝试确保您以正确的用户身份运行,或者您正在使用的用户和/或资源具有正确的权限。

如果您需要某种用户交互,那么您将需要创建一个客户端应用程序并通过 rpc、套接字或命名管道与服务和/或子应用程序进行通信。

Does your console app require user interaction? If so, that's a serious no-no and you should redesign your application. While there are some hacks to make this sort of work in older versions of the OS, this is guaranteed to break in the future.

If your app does not require user interaction, then perhaps your problem is related to the user the service is running as. Try making sure that you run as the correct user, or that the user and/or resources you are using have the right permissions.

If you require some kind of user-interaction, then you will need to create a client application and communicate with the service and/or sub-application via rpc, sockets, or named pipes.

暖树树初阳… 2024-08-10 20:48:18

服务需要连接到服务控制管理器并在启动时提供反馈(即告诉 SCM“我还活着!”)。这就是为什么 C# 应用程序有不同的服务项目模板。您有两种选择:

Services are required to connect to the Service Control Manager and provide feedback at start up (ie. tell SCM 'I'm alive!'). That's why C# application have a different project template for services. You have two alternatives:

  • wrapp your exe on srvany.exe, as described in KB How To Create a User-Defined Service
  • have your C# app detect when is launched as a service (eg. command line param) and switch control to a class that inherits from ServiceBase and properly implements a service.
世态炎凉 2024-08-10 20:48:18

我有一个 Windows 服务,并且我将以下行添加到我的服务的构造函数中:

using System.Diagnostics;
try {
    Process p = Process.Start(@"C:\Windows\system32\calc.exe");
} catch {
    Debugger.Break();
}

当我尝试运行此服务时,进行了 Process.Start() 调用,并且没有发生异常。但是,calc.exe 应用程序没有显示。为了使其正常工作,我在服务控制管理器中编辑了服务的属性,以启用与桌面的交互。完成此操作后,Process.Start() 按预期打开 calc.exe。

但正如其他人所说,与桌面的交互是微软所不赞成的,并且在 Vista 中基本上被禁用了。因此,即使你可以让它在 XP 中运行,我也不知道你是否也能在 Vista 中运行它。

I have a Windows service, and I added the following line to the constructor for my service:

using System.Diagnostics;
try {
    Process p = Process.Start(@"C:\Windows\system32\calc.exe");
} catch {
    Debugger.Break();
}

When I tried to run this, the Process.Start() call was made, and no exception occurred. However, the calc.exe application did not show up. In order to make it work, I had edit the properties for my service in the Service Control Manager to enable interaction with the desktop. After doing that, the Process.Start() opened calc.exe as expected.

But as others have said, interaction with the desktop is frowned upon by Microsoft and has essentially been disabled in Vista. So even if you can get it to work in XP, I don't know that you'll be able to make it work in Vista.

春风十里 2024-08-10 20:48:18

我使用这个类:

class ProcessWrapper : Process, IDisposable
{
    public enum PipeType { StdOut, StdErr }

    public class Output
    {
        public string Message { get; set; }
        public PipeType Pipe { get; set; }
        public override string ToString()
        {
            return $"{Pipe}: {Message}";
        }
    }

    private readonly string _command;
    private readonly string _args;
    private readonly bool _showWindow;
    private bool _isDisposed;

    private readonly Queue<Output> _outputQueue = new Queue<Output>();

    private readonly ManualResetEvent[] _waitHandles = new ManualResetEvent[2];
    private readonly ManualResetEvent _outputSteamWaitHandle = new ManualResetEvent(false);

    public ProcessWrapper(string startCommand, string args, bool showWindow = false)
    {
        _command = startCommand;
        _args = args;
        _showWindow = showWindow;
    }

    public IEnumerable<string> GetMessages()
    {
        while (!_isDisposed)
        {
            _outputSteamWaitHandle.WaitOne();
            if (_outputQueue.Any())
                yield return _outputQueue.Dequeue().ToString();
        }
    }

    public void SendCommand(string command)
    {
        StandardInput.Write(command);
        StandardInput.Flush();
    }

    public new int Start()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = _command,
            Arguments = _args,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            RedirectStandardInput = true,
            CreateNoWindow = !_showWindow
        };
        StartInfo = startInfo;

        OutputDataReceived += delegate (object sender, DataReceivedEventArgs args)
        {
            if (args.Data == null)
            {
                _waitHandles[0].Set();
            }
            else if (args.Data.Length > 0)
            {
                _outputQueue.Enqueue(new Output { Message = args.Data, Pipe = PipeType.StdOut });
                _outputSteamWaitHandle.Set();
            }
        };

        ErrorDataReceived += delegate (object sender, DataReceivedEventArgs args)
        {
            if (args.Data == null)
            {
                _waitHandles[1].Set();
            }
            else if (args.Data.Length > 0)
            {
                _outputSteamWaitHandle.Set();
                _outputQueue.Enqueue(new Output { Message = args.Data, Pipe = PipeType.StdErr });
            }
        };

        base.Start();

        _waitHandles[0] = new ManualResetEvent(false);
        BeginErrorReadLine();
        _waitHandles[1] = new ManualResetEvent(false);
        BeginOutputReadLine();

        return Id;
    }

    public new void Dispose()
    {
        StandardInput.Flush();
        StandardInput.Close();
        if (!WaitForExit(1000))
        {
            Kill();
        }
        if (WaitForExit(1000))
        {
            WaitHandle.WaitAll(_waitHandles);
        }
        base.Dispose();
        _isDisposed = true;
    }
}

I use this class:

class ProcessWrapper : Process, IDisposable
{
    public enum PipeType { StdOut, StdErr }

    public class Output
    {
        public string Message { get; set; }
        public PipeType Pipe { get; set; }
        public override string ToString()
        {
            return 
quot;{Pipe}: {Message}";
        }
    }

    private readonly string _command;
    private readonly string _args;
    private readonly bool _showWindow;
    private bool _isDisposed;

    private readonly Queue<Output> _outputQueue = new Queue<Output>();

    private readonly ManualResetEvent[] _waitHandles = new ManualResetEvent[2];
    private readonly ManualResetEvent _outputSteamWaitHandle = new ManualResetEvent(false);

    public ProcessWrapper(string startCommand, string args, bool showWindow = false)
    {
        _command = startCommand;
        _args = args;
        _showWindow = showWindow;
    }

    public IEnumerable<string> GetMessages()
    {
        while (!_isDisposed)
        {
            _outputSteamWaitHandle.WaitOne();
            if (_outputQueue.Any())
                yield return _outputQueue.Dequeue().ToString();
        }
    }

    public void SendCommand(string command)
    {
        StandardInput.Write(command);
        StandardInput.Flush();
    }

    public new int Start()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = _command,
            Arguments = _args,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            RedirectStandardInput = true,
            CreateNoWindow = !_showWindow
        };
        StartInfo = startInfo;

        OutputDataReceived += delegate (object sender, DataReceivedEventArgs args)
        {
            if (args.Data == null)
            {
                _waitHandles[0].Set();
            }
            else if (args.Data.Length > 0)
            {
                _outputQueue.Enqueue(new Output { Message = args.Data, Pipe = PipeType.StdOut });
                _outputSteamWaitHandle.Set();
            }
        };

        ErrorDataReceived += delegate (object sender, DataReceivedEventArgs args)
        {
            if (args.Data == null)
            {
                _waitHandles[1].Set();
            }
            else if (args.Data.Length > 0)
            {
                _outputSteamWaitHandle.Set();
                _outputQueue.Enqueue(new Output { Message = args.Data, Pipe = PipeType.StdErr });
            }
        };

        base.Start();

        _waitHandles[0] = new ManualResetEvent(false);
        BeginErrorReadLine();
        _waitHandles[1] = new ManualResetEvent(false);
        BeginOutputReadLine();

        return Id;
    }

    public new void Dispose()
    {
        StandardInput.Flush();
        StandardInput.Close();
        if (!WaitForExit(1000))
        {
            Kill();
        }
        if (WaitForExit(1000))
        {
            WaitHandle.WaitAll(_waitHandles);
        }
        base.Dispose();
        _isDisposed = true;
    }
}
猫烠⑼条掵仅有一顆心 2024-08-10 20:48:18

在 Windows 服务中运行任何应用程序(例如“.exe”)都是很奇怪的,因为算法不是那么有效。

Running in Windows Services any application like for example ".exe" is weird to do because the algorithm is not that effective.

幽蝶幻影 2024-08-10 20:48:17

从 Windows Vista 开始,服务无法与桌面交互。您将无法看到从服务启动的任何窗口或控制台窗口。请参阅此MSDN 论坛主题。

在其他操作系统上,服务选项中有一个可用的选项,称为“允许服务与桌面交互”。从技术上讲,您应该为未来进行编程,并且应该遵循 Vista 指南,即使您不在 Vista 上使用它。

如果您仍想运行不与桌面交互的应用程序,请尝试指定进程不使用 shell。

ProcessStartInfo info = new ProcessStartInfo(@"c:\myprogram.exe");
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.CreateNoWindow = true;
info.ErrorDialog = false;
info.WindowStyle = ProcessWindowStyle.Hidden;

Process process = Process.Start(info);

看看这是否有效。

首先,您通知 Windows 该程序不会使用 shell(在 Vista 中无法访问该 shell)。

其次,您将所有控制台交互重定向到内部流(请参阅process.StandardInput 和process.StandardOutput。

Starting from Windows Vista, a service cannot interact with the desktop. You will not be able to see any windows or console windows that are started from a service. See this MSDN forum thread.

On other OS, there is an option that is available in the service option called "Allow Service to interact with desktop". Technically, you should program for the future and should follow the Vista guideline even if you don't use it on Vista.

If you still want to run an application that never interact with the desktop, try specifying the process to not use the shell.

ProcessStartInfo info = new ProcessStartInfo(@"c:\myprogram.exe");
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.CreateNoWindow = true;
info.ErrorDialog = false;
info.WindowStyle = ProcessWindowStyle.Hidden;

Process process = Process.Start(info);

See if this does the trick.

First you inform Windows that the program won't use the shell (which is inaccessible in Vista to service).

Secondly, you redirect all consoles interaction to internal stream (see process.StandardInput and process.StandardOutput.

或十年 2024-08-10 20:48:17

我之前已经成功完成过此操作 - 我家里有一些代码。当我今晚回家时,我将使用启动控制台应用程序的服务的工作代码更新此答案。

我想我会从头开始尝试这个。这是我编写的一些启动控制台应用程序的代码。我将其安装为服务并运行它,它工作正常:cmd.exe 启动(如任务管理器中所示)并持续 10 秒,直到我向它发送退出命令。我希望这对您的情况有所帮助,因为它确实按预期正常工作。

    using (System.Diagnostics.Process process = new System.Diagnostics.Process())
    {
        process.StartInfo = new System.Diagnostics.ProcessStartInfo(@"c:\windows\system32\cmd.exe");
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.ErrorDialog = false;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        process.Start();
        //// do some other things while you wait...
        System.Threading.Thread.Sleep(10000); // simulate doing other things...
        process.StandardInput.WriteLine("exit"); // tell console to exit
        if (!process.HasExited)
        {
            process.WaitForExit(120000); // give 2 minutes for process to finish
            if (!process.HasExited)
            {
                process.Kill(); // took too long, kill it off
            }
        }
    }

I've done this before successfully - I have some code at home. When I get home tonight, I'll update this answer with the working code of a service launching a console app.

I thought I'd try this from scratch. Here's some code I wrote that launches a console app. I installed it as a service and ran it and it worked properly: cmd.exe launches (as seen in Task Manager) and lives for 10 seconds until I send it the exit command. I hope this helps your situation as it does work properly as expected here.

    using (System.Diagnostics.Process process = new System.Diagnostics.Process())
    {
        process.StartInfo = new System.Diagnostics.ProcessStartInfo(@"c:\windows\system32\cmd.exe");
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.ErrorDialog = false;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        process.Start();
        //// do some other things while you wait...
        System.Threading.Thread.Sleep(10000); // simulate doing other things...
        process.StandardInput.WriteLine("exit"); // tell console to exit
        if (!process.HasExited)
        {
            process.WaitForExit(120000); // give 2 minutes for process to finish
            if (!process.HasExited)
            {
                process.Kill(); // took too long, kill it off
            }
        }
    }
未央 2024-08-10 20:48:17

Windows 服务没有 UI。您可以使用此问题中显示的代码将控制台应用的输出重定向到您的服务。

Windows Services do not have UIs. You can redirect the output from a console app to your service with the code shown in this question.

私藏温柔 2024-08-10 20:48:17
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.ServiceProcess;
using System.Runtime.InteropServices;

namespace SystemControl
{
    class Services
    {
        static string strPath = @"D:\";
        static void Main(string[] args)
        {
            string strServiceName = "WindowsService1";
            CreateFolderStructure(strPath);
            string svcPath = @"D:\Applications\MSC\Agent\bin\WindowsService1.exe";
            if (!IsInstalled(strServiceName))
            {
                InstallAndStart(strServiceName, strServiceName, svcPath + " -k runservice");                
            }
            else
            {
                Console.Write(strServiceName + " already installed. Do you want to Uninstalled the Service.Y/N.?");
                string strKey = Console.ReadLine();

                if (!string.IsNullOrEmpty(strKey) && (strKey.StartsWith("y")|| strKey.StartsWith("Y")))
                {
                    StopService(strServiceName);
                    Uninstall(strServiceName);
                    ServiceLogs(strServiceName + " Uninstalled.!", strPath);
                    Console.Write(strServiceName + " Uninstalled.!");
                    Console.Read();
                }
            }
        }

        #region "Environment Variables"
        public static string GetEnvironment(string name, bool ExpandVariables = true)
        {
            if (ExpandVariables)
            {
                return System.Environment.GetEnvironmentVariable(name);
            }
            else
            {
                return (string)Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment\").GetValue(name, "", Microsoft.Win32.RegistryValueOptions.DoNotExpandEnvironmentNames);
            }
        }

        public static void SetEnvironment(string name, string value)
        {
            System.Environment.SetEnvironmentVariable(name, value);
        }
        #endregion

        #region "ServiceCalls Native"
        public static ServiceController[] List { get { return ServiceController.GetServices(); } }

        public static void Start(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running, timeout);
            }
            catch(Exception ex)
            {
                // ...
            }
        }

        public static void Stop(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
            }
            catch
            {
                // ...
            }
        }

        public static void Restart(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                int millisec1 = Environment.TickCount;
                TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);

                // count the rest of the timeout
                int millisec2 = Environment.TickCount;
                timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2 - millisec1));

                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running, timeout);
            }
            catch
            {
                // ...
            }
        }

        public static bool IsInstalled(string serviceName)
        {
            // get list of Windows services
            ServiceController[] services = ServiceController.GetServices();

            // try to find service name
            foreach (ServiceController service in services)
            {
                if (service.ServiceName == serviceName)
                    return true;
            }
            return false;
        }
        #endregion

        #region "ServiceCalls API"
        private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
        private const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;

        [Flags]
        public enum ServiceManagerRights
        {
            Connect = 0x0001,
            CreateService = 0x0002,
            EnumerateService = 0x0004,
            Lock = 0x0008,
            QueryLockStatus = 0x0010,
            ModifyBootConfig = 0x0020,
            StandardRightsRequired = 0xF0000,
            AllAccess = (StandardRightsRequired | Connect | CreateService |
            EnumerateService | Lock | QueryLockStatus | ModifyBootConfig)
        }

        [Flags]
        public enum ServiceRights
        {
            QueryConfig = 0x1,
            ChangeConfig = 0x2,
            QueryStatus = 0x4,
            EnumerateDependants = 0x8,
            Start = 0x10,
            Stop = 0x20,
            PauseContinue = 0x40,
            Interrogate = 0x80,
            UserDefinedControl = 0x100,
            Delete = 0x00010000,
            StandardRightsRequired = 0xF0000,
            AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig |
            QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
            Interrogate | UserDefinedControl)
        }

        public enum ServiceBootFlag
        {
            Start = 0x00000000,
            SystemStart = 0x00000001,
            AutoStart = 0x00000002,
            DemandStart = 0x00000003,
            Disabled = 0x00000004
        }

        public enum ServiceState
        {
            Unknown = -1, // The state cannot be (has not been) retrieved.
            NotFound = 0, // The service is not known on the host server.
            Stop = 1, // The service is NET stopped.
            Run = 2, // The service is NET started.
            Stopping = 3,
            Starting = 4,
        }

        public enum ServiceControl
        {
            Stop = 0x00000001,
            Pause = 0x00000002,
            Continue = 0x00000003,
            Interrogate = 0x00000004,
            Shutdown = 0x00000005,
            ParamChange = 0x00000006,
            NetBindAdd = 0x00000007,
            NetBindRemove = 0x00000008,
            NetBindEnable = 0x00000009,
            NetBindDisable = 0x0000000A
        }

        public enum ServiceError
        {
            Ignore = 0x00000000,
            Normal = 0x00000001,
            Severe = 0x00000002,
            Critical = 0x00000003
        }

        [StructLayout(LayoutKind.Sequential)]
        private class SERVICE_STATUS
        {
            public int dwServiceType = 0;
            public ServiceState dwCurrentState = 0;
            public int dwControlsAccepted = 0;
            public int dwWin32ExitCode = 0;
            public int dwServiceSpecificExitCode = 0;
            public int dwCheckPoint = 0;
            public int dwWaitHint = 0;
        }

        [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerA")]
        private static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, ServiceManagerRights dwDesiredAccess);
        [DllImport("advapi32.dll", EntryPoint = "OpenServiceA", CharSet = CharSet.Ansi)]
        private static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceRights dwDesiredAccess);
        [DllImport("advapi32.dll", EntryPoint = "CreateServiceA")]
        private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword);
        [DllImport("advapi32.dll")]
        private static extern int CloseServiceHandle(IntPtr hSCObject);
        [DllImport("advapi32.dll")]
        private static extern int QueryServiceStatus(IntPtr hService, SERVICE_STATUS lpServiceStatus);
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern int DeleteService(IntPtr hService);
        [DllImport("advapi32.dll")]
        private static extern int ControlService(IntPtr hService, ServiceControl dwControl, SERVICE_STATUS lpServiceStatus);
        [DllImport("advapi32.dll", EntryPoint = "StartServiceA")]
        private static extern int StartService(IntPtr hService, int dwNumServiceArgs, int lpServiceArgVectors);

        /// <summary>
        /// Takes a service name and tries to stop and then uninstall the windows serviceError
        /// </summary>
        /// <param name="ServiceName">The windows service name to uninstall</param>
        public static void Uninstall(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr service = OpenService(scman, ServiceName, ServiceRights.StandardRightsRequired | ServiceRights.Stop | ServiceRights.QueryStatus);
                if (service == IntPtr.Zero)
                {
                    throw new ApplicationException("Service not installed.");
                }
                try
                {
                    StopService(service);
                    int ret = DeleteService(service);
                    if (ret == 0)
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new ApplicationException("Could not delete service " + error);
                    }
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Accepts a service name and returns true if the service with that service name exists
        /// </summary>
        /// <param name="ServiceName">The service name that we will check for existence</param>
        /// <returns>True if that service exists false otherwise</returns>
        public static bool ServiceIsInstalled(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr service = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus);
                if (service == IntPtr.Zero) return false;
                CloseServiceHandle(service);
                return true;
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Takes a service name, a service display name and the path to the service executable and installs / starts the windows service.
        /// </summary>
        /// <param name="ServiceName">The service name that this service will have</param>
        /// <param name="DisplayName">The display name that this service will have</param>
        /// <param name="FileName">The path to the executable of the service</param>
        public static void InstallAndStart(string ServiceName, string DisplayName,
        string FileName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect |
            ServiceManagerRights.CreateService);
            try
            {
                string strKey = string.Empty;
                IntPtr service = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus | ServiceRights.Start);
                if (service == IntPtr.Zero)
                {
                    service = CreateService(scman, ServiceName, DisplayName,
                    ServiceRights.QueryStatus | ServiceRights.Start, SERVICE_WIN32_OWN_PROCESS,
                    ServiceBootFlag.AutoStart, ServiceError.Normal, FileName, null, IntPtr.Zero,
                    null, null, null);
                    ServiceLogs(ServiceName + " Installed Sucessfully.!", strPath);
                    Console.Write(ServiceName + " Installed Sucessfully.! Do you want to Start the Service.Y/N.?");
                    strKey=Console.ReadLine();
                }
                if (service == IntPtr.Zero)
                {
                    ServiceLogs("Failed to install service.", strPath);
                    throw new ApplicationException("Failed to install service.");
                }
                try
                {
                    if (!string.IsNullOrEmpty(strKey) && (strKey.StartsWith("y") || strKey.StartsWith("Y")))
                    {
                        StartService(service);
                        ServiceLogs(ServiceName + " Started Sucessfully.!", strPath);
                        Console.Write(ServiceName + " Started Sucessfully.!");
                        Console.Read();
                    }
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Takes a service name and starts it
        /// </summary>
        /// <param name="Name">The service name</param>
        public static void StartService(string Name)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, Name, ServiceRights.QueryStatus |
                ServiceRights.Start);
                if (hService == IntPtr.Zero)
                {
                    ServiceLogs("Could not open service.", strPath);
                    throw new ApplicationException("Could not open service.");
                }
                try
                {
                    StartService(hService);
                }
                finally
                {
                    CloseServiceHandle(hService);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Stops the provided windows service
        /// </summary>
        /// <param name="Name">The service name that will be stopped</param>
        public static void StopService(string Name)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, Name, ServiceRights.QueryStatus |
                ServiceRights.Stop);
                if (hService == IntPtr.Zero)
                {
                    ServiceLogs("Could not open service.", strPath);
                    throw new ApplicationException("Could not open service.");
                }
                try
                {
                    StopService(hService);
                }
                finally
                {
                    CloseServiceHandle(hService);
                }



}
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Stars the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the windows service</param>
        private static void StartService(IntPtr hService)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();
            StartService(hService, 0, 0);
            WaitForServiceStatus(hService, ServiceState.Starting, ServiceState.Run);
        }

        /// <summary>
        /// Stops the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the windows service</param>
        private static void StopService(IntPtr hService)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();
            ControlService(hService, ServiceControl.Stop, status);
            WaitForServiceStatus(hService, ServiceState.Stopping, ServiceState.Stop);
        }

        /// <summary>
        /// Takes a service name and returns the <code>ServiceState</code> of the corresponding service
        /// </summary>
        /// <param name="ServiceName">The service name that we will check for his <code>ServiceState</code></param>
        /// <returns>The ServiceState of the service we wanted to check</returns>
        public static ServiceState GetServiceStatus(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus);
                if (hService == IntPtr.Zero)
                {
                    return ServiceState.NotFound;
                }
                try
                {
                    return GetServiceStatus(hService);
                }
                finally
                {
                    CloseServiceHandle(scman);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Gets the service state by using the handle of the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the service</param>
        /// <returns>The <code>ServiceState</code> of the service</returns>
        private static ServiceState GetServiceStatus(IntPtr hService)
        {
            SERVICE_STATUS ssStatus = new SERVICE_STATUS();
            if (QueryServiceStatus(hService, ssStatus) == 0)
            {
                ServiceLogs("Failed to query service status.", strPath);
                throw new ApplicationException("Failed to query service status.");
            }
            return ssStatus.dwCurrentState;
        }

        /// <summary>
        /// Returns true when the service status has been changes from wait status to desired status
        /// ,this method waits around 10 seconds for this operation.
        /// </summary>
        /// <param name="hService">The handle to the service</param>
        /// <param name="WaitStatus">The current state of the service</param>
        /// <param name="DesiredStatus">The desired state of the service</param>
        /// <returns>bool if the service has successfully changed states within the allowed timeline</returns>
        private static bool WaitForServiceStatus(IntPtr hService, ServiceState
        WaitStatus, ServiceState DesiredStatus)
        {
            SERVICE_STATUS ssStatus = new SERVICE_STATUS();
            int dwOldCheckPoint;
            int dwStartTickCount;

            QueryServiceStatus(hService, ssStatus);
            if (ssStatus.dwCurrentState == DesiredStatus) return true;
            dwStartTickCount = Environment.TickCount;
            dwOldCheckPoint = ssStatus.dwCheckPoint;

            while (ssStatus.dwCurrentState == WaitStatus)
            {
                // Do not wait longer than the wait hint. A good interval is
                // one tenth the wait hint, but no less than 1 second and no
                // more than 10 seconds.

                int dwWaitTime = ssStatus.dwWaitHint / 10;

                if (dwWaitTime < 1000) dwWaitTime = 1000;
                else if (dwWaitTime > 10000) dwWaitTime = 10000;

                System.Threading.Thread.Sleep(dwWaitTime);

                // Check the status again.

                if (QueryServiceStatus(hService, ssStatus) == 0) break;

                if (ssStatus.dwCheckPoint > dwOldCheckPoint)
                {
                    // The service is making progress.
                    dwStartTickCount = Environment.TickCount;
                    dwOldCheckPoint = ssStatus.dwCheckPoint;
                }
                else
                {
                    if (Environment.TickCount - dwStartTickCount > ssStatus.dwWaitHint)
                    {
                        // No progress made within the wait hint
                        break;
                    }
                }
            }
            return (ssStatus.dwCurrentState == DesiredStatus);
        }

        /// <summary>
        /// Opens the service manager
        /// </summary>
        /// <param name="Rights">The service manager rights</param>
        /// <returns>the handle to the service manager</returns>
        private static IntPtr OpenSCManager(ServiceManagerRights Rights)
        {
            IntPtr scman = OpenSCManager(null, null, Rights);
            if (scman == IntPtr.Zero)
            {
                try
                {
                    throw new ApplicationException("Could not connect to service control manager.");
                }
                catch (Exception ex)
                {
                }
            }
            return scman;
        }

        #endregion

        #region"CreateFolderStructure"
        private static void CreateFolderStructure(string path)
        {
            if(!System.IO.Directory.Exists(path+"Applications"))
                System.IO.Directory.CreateDirectory(path+ "Applications");
            if (!System.IO.Directory.Exists(path + "Applications\\MSC"))
                System.IO.Directory.CreateDirectory(path + "Applications\\MSC");
            if (!System.IO.Directory.Exists(path + "Applications\\MSC\\Agent"))
                System.IO.Directory.CreateDirectory(path + "Applications\\MSC\\Agent");
            if (!System.IO.Directory.Exists(path + "Applications\\MSC\\Agent\\bin"))
                System.IO.Directory.CreateDirectory(path + "Applications\\MSC\\Agent\\bin");
            if (!System.IO.Directory.Exists(path + "Applications\\MSC\\AgentService"))
                System.IO.Directory.CreateDirectory(path + "Applications\\MSC\\AgentService");

            string fullPath = System.IO.Path.GetFullPath("MSCService");
            if (System.IO.Directory.Exists(fullPath))
            {
                foreach (string strFile in System.IO.Directory.GetFiles(fullPath))
                {
                    if (System.IO.File.Exists(strFile))
                    {
                        String[] strArr = strFile.Split('\\');
                        System.IO.File.Copy(strFile, path + "Applications\\MSC\\Agent\\bin\\"+ strArr[strArr.Count()-1], true);
                    }
                }
            }            
        }
        #endregion

        private static void ServiceLogs(string strLogInfo, string path)
        {
            string filePath = path + "Applications\\MSC\\AgentService\\ServiceLogs.txt";            
            System.IO.File.AppendAllLines(filePath, (strLogInfo + "--" + DateTime.Now.ToString()).ToString().Split('|'));
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.ServiceProcess;
using System.Runtime.InteropServices;

namespace SystemControl
{
    class Services
    {
        static string strPath = @"D:\";
        static void Main(string[] args)
        {
            string strServiceName = "WindowsService1";
            CreateFolderStructure(strPath);
            string svcPath = @"D:\Applications\MSC\Agent\bin\WindowsService1.exe";
            if (!IsInstalled(strServiceName))
            {
                InstallAndStart(strServiceName, strServiceName, svcPath + " -k runservice");                
            }
            else
            {
                Console.Write(strServiceName + " already installed. Do you want to Uninstalled the Service.Y/N.?");
                string strKey = Console.ReadLine();

                if (!string.IsNullOrEmpty(strKey) && (strKey.StartsWith("y")|| strKey.StartsWith("Y")))
                {
                    StopService(strServiceName);
                    Uninstall(strServiceName);
                    ServiceLogs(strServiceName + " Uninstalled.!", strPath);
                    Console.Write(strServiceName + " Uninstalled.!");
                    Console.Read();
                }
            }
        }

        #region "Environment Variables"
        public static string GetEnvironment(string name, bool ExpandVariables = true)
        {
            if (ExpandVariables)
            {
                return System.Environment.GetEnvironmentVariable(name);
            }
            else
            {
                return (string)Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment\").GetValue(name, "", Microsoft.Win32.RegistryValueOptions.DoNotExpandEnvironmentNames);
            }
        }

        public static void SetEnvironment(string name, string value)
        {
            System.Environment.SetEnvironmentVariable(name, value);
        }
        #endregion

        #region "ServiceCalls Native"
        public static ServiceController[] List { get { return ServiceController.GetServices(); } }

        public static void Start(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running, timeout);
            }
            catch(Exception ex)
            {
                // ...
            }
        }

        public static void Stop(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
            }
            catch
            {
                // ...
            }
        }

        public static void Restart(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                int millisec1 = Environment.TickCount;
                TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);

                // count the rest of the timeout
                int millisec2 = Environment.TickCount;
                timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2 - millisec1));

                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running, timeout);
            }
            catch
            {
                // ...
            }
        }

        public static bool IsInstalled(string serviceName)
        {
            // get list of Windows services
            ServiceController[] services = ServiceController.GetServices();

            // try to find service name
            foreach (ServiceController service in services)
            {
                if (service.ServiceName == serviceName)
                    return true;
            }
            return false;
        }
        #endregion

        #region "ServiceCalls API"
        private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
        private const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;

        [Flags]
        public enum ServiceManagerRights
        {
            Connect = 0x0001,
            CreateService = 0x0002,
            EnumerateService = 0x0004,
            Lock = 0x0008,
            QueryLockStatus = 0x0010,
            ModifyBootConfig = 0x0020,
            StandardRightsRequired = 0xF0000,
            AllAccess = (StandardRightsRequired | Connect | CreateService |
            EnumerateService | Lock | QueryLockStatus | ModifyBootConfig)
        }

        [Flags]
        public enum ServiceRights
        {
            QueryConfig = 0x1,
            ChangeConfig = 0x2,
            QueryStatus = 0x4,
            EnumerateDependants = 0x8,
            Start = 0x10,
            Stop = 0x20,
            PauseContinue = 0x40,
            Interrogate = 0x80,
            UserDefinedControl = 0x100,
            Delete = 0x00010000,
            StandardRightsRequired = 0xF0000,
            AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig |
            QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
            Interrogate | UserDefinedControl)
        }

        public enum ServiceBootFlag
        {
            Start = 0x00000000,
            SystemStart = 0x00000001,
            AutoStart = 0x00000002,
            DemandStart = 0x00000003,
            Disabled = 0x00000004
        }

        public enum ServiceState
        {
            Unknown = -1, // The state cannot be (has not been) retrieved.
            NotFound = 0, // The service is not known on the host server.
            Stop = 1, // The service is NET stopped.
            Run = 2, // The service is NET started.
            Stopping = 3,
            Starting = 4,
        }

        public enum ServiceControl
        {
            Stop = 0x00000001,
            Pause = 0x00000002,
            Continue = 0x00000003,
            Interrogate = 0x00000004,
            Shutdown = 0x00000005,
            ParamChange = 0x00000006,
            NetBindAdd = 0x00000007,
            NetBindRemove = 0x00000008,
            NetBindEnable = 0x00000009,
            NetBindDisable = 0x0000000A
        }

        public enum ServiceError
        {
            Ignore = 0x00000000,
            Normal = 0x00000001,
            Severe = 0x00000002,
            Critical = 0x00000003
        }

        [StructLayout(LayoutKind.Sequential)]
        private class SERVICE_STATUS
        {
            public int dwServiceType = 0;
            public ServiceState dwCurrentState = 0;
            public int dwControlsAccepted = 0;
            public int dwWin32ExitCode = 0;
            public int dwServiceSpecificExitCode = 0;
            public int dwCheckPoint = 0;
            public int dwWaitHint = 0;
        }

        [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerA")]
        private static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, ServiceManagerRights dwDesiredAccess);
        [DllImport("advapi32.dll", EntryPoint = "OpenServiceA", CharSet = CharSet.Ansi)]
        private static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceRights dwDesiredAccess);
        [DllImport("advapi32.dll", EntryPoint = "CreateServiceA")]
        private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword);
        [DllImport("advapi32.dll")]
        private static extern int CloseServiceHandle(IntPtr hSCObject);
        [DllImport("advapi32.dll")]
        private static extern int QueryServiceStatus(IntPtr hService, SERVICE_STATUS lpServiceStatus);
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern int DeleteService(IntPtr hService);
        [DllImport("advapi32.dll")]
        private static extern int ControlService(IntPtr hService, ServiceControl dwControl, SERVICE_STATUS lpServiceStatus);
        [DllImport("advapi32.dll", EntryPoint = "StartServiceA")]
        private static extern int StartService(IntPtr hService, int dwNumServiceArgs, int lpServiceArgVectors);

        /// <summary>
        /// Takes a service name and tries to stop and then uninstall the windows serviceError
        /// </summary>
        /// <param name="ServiceName">The windows service name to uninstall</param>
        public static void Uninstall(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr service = OpenService(scman, ServiceName, ServiceRights.StandardRightsRequired | ServiceRights.Stop | ServiceRights.QueryStatus);
                if (service == IntPtr.Zero)
                {
                    throw new ApplicationException("Service not installed.");
                }
                try
                {
                    StopService(service);
                    int ret = DeleteService(service);
                    if (ret == 0)
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new ApplicationException("Could not delete service " + error);
                    }
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Accepts a service name and returns true if the service with that service name exists
        /// </summary>
        /// <param name="ServiceName">The service name that we will check for existence</param>
        /// <returns>True if that service exists false otherwise</returns>
        public static bool ServiceIsInstalled(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr service = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus);
                if (service == IntPtr.Zero) return false;
                CloseServiceHandle(service);
                return true;
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Takes a service name, a service display name and the path to the service executable and installs / starts the windows service.
        /// </summary>
        /// <param name="ServiceName">The service name that this service will have</param>
        /// <param name="DisplayName">The display name that this service will have</param>
        /// <param name="FileName">The path to the executable of the service</param>
        public static void InstallAndStart(string ServiceName, string DisplayName,
        string FileName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect |
            ServiceManagerRights.CreateService);
            try
            {
                string strKey = string.Empty;
                IntPtr service = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus | ServiceRights.Start);
                if (service == IntPtr.Zero)
                {
                    service = CreateService(scman, ServiceName, DisplayName,
                    ServiceRights.QueryStatus | ServiceRights.Start, SERVICE_WIN32_OWN_PROCESS,
                    ServiceBootFlag.AutoStart, ServiceError.Normal, FileName, null, IntPtr.Zero,
                    null, null, null);
                    ServiceLogs(ServiceName + " Installed Sucessfully.!", strPath);
                    Console.Write(ServiceName + " Installed Sucessfully.! Do you want to Start the Service.Y/N.?");
                    strKey=Console.ReadLine();
                }
                if (service == IntPtr.Zero)
                {
                    ServiceLogs("Failed to install service.", strPath);
                    throw new ApplicationException("Failed to install service.");
                }
                try
                {
                    if (!string.IsNullOrEmpty(strKey) && (strKey.StartsWith("y") || strKey.StartsWith("Y")))
                    {
                        StartService(service);
                        ServiceLogs(ServiceName + " Started Sucessfully.!", strPath);
                        Console.Write(ServiceName + " Started Sucessfully.!");
                        Console.Read();
                    }
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Takes a service name and starts it
        /// </summary>
        /// <param name="Name">The service name</param>
        public static void StartService(string Name)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, Name, ServiceRights.QueryStatus |
                ServiceRights.Start);
                if (hService == IntPtr.Zero)
                {
                    ServiceLogs("Could not open service.", strPath);
                    throw new ApplicationException("Could not open service.");
                }
                try
                {
                    StartService(hService);
                }
                finally
                {
                    CloseServiceHandle(hService);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Stops the provided windows service
        /// </summary>
        /// <param name="Name">The service name that will be stopped</param>
        public static void StopService(string Name)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, Name, ServiceRights.QueryStatus |
                ServiceRights.Stop);
                if (hService == IntPtr.Zero)
                {
                    ServiceLogs("Could not open service.", strPath);
                    throw new ApplicationException("Could not open service.");
                }
                try
                {
                    StopService(hService);
                }
                finally
                {
                    CloseServiceHandle(hService);
                }



}
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Stars the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the windows service</param>
        private static void StartService(IntPtr hService)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();
            StartService(hService, 0, 0);
            WaitForServiceStatus(hService, ServiceState.Starting, ServiceState.Run);
        }

        /// <summary>
        /// Stops the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the windows service</param>
        private static void StopService(IntPtr hService)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();
            ControlService(hService, ServiceControl.Stop, status);
            WaitForServiceStatus(hService, ServiceState.Stopping, ServiceState.Stop);
        }

        /// <summary>
        /// Takes a service name and returns the <code>ServiceState</code> of the corresponding service
        /// </summary>
        /// <param name="ServiceName">The service name that we will check for his <code>ServiceState</code></param>
        /// <returns>The ServiceState of the service we wanted to check</returns>
        public static ServiceState GetServiceStatus(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus);
                if (hService == IntPtr.Zero)
                {
                    return ServiceState.NotFound;
                }
                try
                {
                    return GetServiceStatus(hService);
                }
                finally
                {
                    CloseServiceHandle(scman);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Gets the service state by using the handle of the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the service</param>
        /// <returns>The <code>ServiceState</code> of the service</returns>
        private static ServiceState GetServiceStatus(IntPtr hService)
        {
            SERVICE_STATUS ssStatus = new SERVICE_STATUS();
            if (QueryServiceStatus(hService, ssStatus) == 0)
            {
                ServiceLogs("Failed to query service status.", strPath);
                throw new ApplicationException("Failed to query service status.");
            }
            return ssStatus.dwCurrentState;
        }

        /// <summary>
        /// Returns true when the service status has been changes from wait status to desired status
        /// ,this method waits around 10 seconds for this operation.
        /// </summary>
        /// <param name="hService">The handle to the service</param>
        /// <param name="WaitStatus">The current state of the service</param>
        /// <param name="DesiredStatus">The desired state of the service</param>
        /// <returns>bool if the service has successfully changed states within the allowed timeline</returns>
        private static bool WaitForServiceStatus(IntPtr hService, ServiceState
        WaitStatus, ServiceState DesiredStatus)
        {
            SERVICE_STATUS ssStatus = new SERVICE_STATUS();
            int dwOldCheckPoint;
            int dwStartTickCount;

            QueryServiceStatus(hService, ssStatus);
            if (ssStatus.dwCurrentState == DesiredStatus) return true;
            dwStartTickCount = Environment.TickCount;
            dwOldCheckPoint = ssStatus.dwCheckPoint;

            while (ssStatus.dwCurrentState == WaitStatus)
            {
                // Do not wait longer than the wait hint. A good interval is
                // one tenth the wait hint, but no less than 1 second and no
                // more than 10 seconds.

                int dwWaitTime = ssStatus.dwWaitHint / 10;

                if (dwWaitTime < 1000) dwWaitTime = 1000;
                else if (dwWaitTime > 10000) dwWaitTime = 10000;

                System.Threading.Thread.Sleep(dwWaitTime);

                // Check the status again.

                if (QueryServiceStatus(hService, ssStatus) == 0) break;

                if (ssStatus.dwCheckPoint > dwOldCheckPoint)
                {
                    // The service is making progress.
                    dwStartTickCount = Environment.TickCount;
                    dwOldCheckPoint = ssStatus.dwCheckPoint;
                }
                else
                {
                    if (Environment.TickCount - dwStartTickCount > ssStatus.dwWaitHint)
                    {
                        // No progress made within the wait hint
                        break;
                    }
                }
            }
            return (ssStatus.dwCurrentState == DesiredStatus);
        }

        /// <summary>
        /// Opens the service manager
        /// </summary>
        /// <param name="Rights">The service manager rights</param>
        /// <returns>the handle to the service manager</returns>
        private static IntPtr OpenSCManager(ServiceManagerRights Rights)
        {
            IntPtr scman = OpenSCManager(null, null, Rights);
            if (scman == IntPtr.Zero)
            {
                try
                {
                    throw new ApplicationException("Could not connect to service control manager.");
                }
                catch (Exception ex)
                {
                }
            }
            return scman;
        }

        #endregion

        #region"CreateFolderStructure"
        private static void CreateFolderStructure(string path)
        {
            if(!System.IO.Directory.Exists(path+"Applications"))
                System.IO.Directory.CreateDirectory(path+ "Applications");
            if (!System.IO.Directory.Exists(path + "Applications\\MSC"))
                System.IO.Directory.CreateDirectory(path + "Applications\\MSC");
            if (!System.IO.Directory.Exists(path + "Applications\\MSC\\Agent"))
                System.IO.Directory.CreateDirectory(path + "Applications\\MSC\\Agent");
            if (!System.IO.Directory.Exists(path + "Applications\\MSC\\Agent\\bin"))
                System.IO.Directory.CreateDirectory(path + "Applications\\MSC\\Agent\\bin");
            if (!System.IO.Directory.Exists(path + "Applications\\MSC\\AgentService"))
                System.IO.Directory.CreateDirectory(path + "Applications\\MSC\\AgentService");

            string fullPath = System.IO.Path.GetFullPath("MSCService");
            if (System.IO.Directory.Exists(fullPath))
            {
                foreach (string strFile in System.IO.Directory.GetFiles(fullPath))
                {
                    if (System.IO.File.Exists(strFile))
                    {
                        String[] strArr = strFile.Split('\\');
                        System.IO.File.Copy(strFile, path + "Applications\\MSC\\Agent\\bin\\"+ strArr[strArr.Count()-1], true);
                    }
                }
            }            
        }
        #endregion

        private static void ServiceLogs(string strLogInfo, string path)
        {
            string filePath = path + "Applications\\MSC\\AgentService\\ServiceLogs.txt";            
            System.IO.File.AppendAllLines(filePath, (strLogInfo + "--" + DateTime.Now.ToString()).ToString().Split('|'));
        }
    }
}
酒中人 2024-08-10 20:48:17

正如 pierre 所说,没有办法为 Windows 服务提供用户界面(或者没有简单的方法)。在这种情况下,我所做的就是拥有一个设置文件,无论服务运行的时间间隔如何,都可以从服务中读取该设置文件,并拥有一个独立的应用程序来更改设置文件。

As pierre said, there is no way to have a user interface for a windows service (or no easy way). What I do in that kind of situation is to have a settings file that is read from the service on whatever interval the service operates on and have a standalone application that makes changes to the settings file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文