製作本地服務監視主程序的運行

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自帶的有,百度查下吧。沒時間了,先寫到這。

 

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