制作本地服务监视主程序的运行
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自带的有,百度查下吧。没时间了,先写到这。