制作本地服务监视主程序的运行

vs自带的有本地服务项目,创建即可。这些不多说了,好多博客都有,我只说几点注意的点:

1、

 

 选localsystem,选localservice不行,不知道为啥

2、对于我的功能是要监控主程序是否运行,没运行的,我需要把主程序启动,这个是比较麻烦的,因为服务是不能启动exe的,具体原因好像是本地服务和winform程序不在同一消息队列还是什么的具体忘了,后来也是查了半天找到的方法。

public class SoftStart
    {
        public static void Start(string commandLine, bool showWindow)
        {
            IntPtr hToken;
            IntPtr hTokenDup;
            const int TOKEN_ALL_ACCESS = 268435456;
            const int TokenSessionId = 12;
            const uint CREATE_PROCESS_FLAGS = 0x00000020 | 0x00000010 | 0x400;

            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, out hToken))
            {
                //throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            var sa = new SECURITY_ATTRIBUTES();
            sa.bInheritHandle = true;
            sa.Length = Marshal.SizeOf(sa);

            if (!DuplicateTokenEx(hToken, 268435456, ref sa, 1, 1, out hTokenDup))
            {
                var error = Marshal.GetLastWin32Error();
                CloseHandle(hToken);
                //throw new Win32Exception(error);
            }

            var si = new STARTUPINFO();
            si.cb = Marshal.SizeOf(si);
            si.lpDesktop = "WinSta0\\Default";
            if (!showWindow)
            {
                si.dwFlags = 1;//STARTF
                si.wShowWindow = 0;
            }
            IntPtr pEnv;
            var dwSessionId = WTSGetActiveConsoleSessionId();

            if (!SetTokenInformation(hTokenDup, TokenSessionId, out dwSessionId, sizeof(uint)))
            {
                var error = Marshal.GetLastWin32Error();
                CloseHandle(hToken);
                CloseHandle(hTokenDup);
                //throw new Win32Exception(error);
            }

            if (!CreateEnvironmentBlock(out pEnv, hTokenDup, 0))
            {
                var error = Marshal.GetLastWin32Error();
                CloseHandle(hToken);
                CloseHandle(hTokenDup);
                //throw new Win32Exception(error);
            }

            PROCESS_INFORMATION pro;
            if (!CreateProcessAsUser(hTokenDup, null, commandLine, ref sa, ref sa, true, CREATE_PROCESS_FLAGS, pEnv, null, ref si, out pro))
            {
                var error = Marshal.GetLastWin32Error();
                CloseHandle(hToken);
                CloseHandle(hTokenDup);
                //throw new Win32Exception(error);
            }

            if (pEnv != IntPtr.Zero)
            {
                DestroyEnvironmentBlock(pEnv);
            }

            CloseHandle(hToken);
            CloseHandle(hTokenDup);
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool SetTokenInformation(IntPtr TokenHandle, int TokenInformationClass, out IntPtr TokenInformation, int TokenInformationLength);
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, out IntPtr TokenHandle);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr GetCurrentProcess();
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr WTSGetActiveConsoleSessionId();
        [DllImport("Userenv.dll", SetLastError = true)]
        public static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment);
        [DllImport("Userenv.dll", SetLastError = true)]
        public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, int bInherit);
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool DuplicateTokenEx(IntPtr hExistingToken, int dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int ImpersonationLevel, int dwTokenType, out IntPtr phNewToken);
        [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, uint dwCreationFlags, IntPtr lpEnvrionment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CloseHandle(IntPtr handle);
        public struct SECURITY_ATTRIBUTES
        {
            public int Length;

            public IntPtr lpSecurityDescriptor;

            public bool bInheritHandle;
        }
        public struct STARTUPINFO
        {
            public int cb;

            public string lpReserved;

            public string lpDesktop;

            public string lpTitle;

            public uint dwX;

            public uint dwY;

            public uint dwXSize;

            public uint dwYSize;

            public uint dwXCountChars;

            public uint dwYCountChars;

            public uint dwFillAttribute;

            public uint dwFlags;

            public short wShowWindow;

            public short cbReserved2;

            public IntPtr lpReserved2;

            public IntPtr hStdInput;

            public IntPtr hStdOutput;

            public IntPtr hStdError;
        }
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;

            public IntPtr hThread;

            public int dwProcessID;

            public int dwThreadID;
        }
    }

调用:SoftStart.Start(path,true);path是你要启动的exe地址,true是要显示ui。

具体项目源码:https://files.cnblogs.com/files/dachuang/WindowsServiceTest.zip?t=1658840431,用的是vs2019.

制作完本地服务项目后,需要在主程序安装和启动此服务,代码如下:

//调用安装并启动本地服务
LocalServiceMgr lsm = new LocalServiceMgr();
lsm.CheckService("eams-protect");//服务名

public class LocalServiceMgr
    {
        public void CheckService(string serviceName)
        {
            ServiceController[] services = ServiceController.GetServices();
            foreach (ServiceController s in services)
            {
                if (s.ServiceName == serviceName)
                {
                    if (s.Status == ServiceControllerStatus.Running || s.Status == ServiceControllerStatus.StartPending)
                        return;
                    else
                    {
                        s.Start();
                        return;
                    }
                }
            }
            Start();
        }

        /// <summary>
        /// 安装并启动本地守护服务
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            Common.LogHelper.getLogHelper().WriteLog("开始安装开启服务");
            try
            {
                //创建启动对象
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory+ "LocalService\\";
                startInfo.UseShellExecute = false;
                startInfo.CreateNoWindow = true;
                startInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + "LocalService\\Install.bat";
                //设置启动动作,确保以管理员身份运行
                startInfo.Verb = "runas";
                Process.Start(startInfo);
                return true;
            }
            catch(Exception ex)
            {
                Common.LogHelper.getLogHelper().WriteLog("安装开启服务出错", ex);
                return false;
            }
        }
        /// <summary>
        /// 卸载本地守护服务
        /// </summary>
        /// <returns></returns>
        public bool Stop()
        {
            try
            {
                //创建启动对象
                System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
                startInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
                startInfo.UseShellExecute = false;
                startInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + "LocalService\\Uninstall.bat";
                //设置启动动作,确保以管理员身份运行
                startInfo.Verb = "runas";
                Process.Start(startInfo);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }

 

卸载:

 

 

 里面的InstallUtil是windows自带的有,百度查下吧。没时间了,先写到这。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章