现在的位置: 首页 > 综合 > 正文

window service 恢复选项卡设置

2012年05月28日 ⁄ 综合 ⁄ 共 7311字 ⁄ 字号 评论关闭
  1 class 设置服务恢复选项
  2     {
  3         public static void Main(string[] args)
  4         {
  6             ServiceRecovery.UpdateServiceConfig("DEMO");
  7             Console.WriteLine("ok");
  8         }
  9     }
 10 
 11     class ServiceRecovery
 12     {
 13         #region NativeMethod
 14         
 15         [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 16         [return: MarshalAs(UnmanagedType.Bool)]
 17         public static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, IntPtr lpInfo);
 18 
 19         [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 20         public static extern IntPtr OpenSCManager(string MachineName, string DatabaseName, uint DesiredAcces);
 21 
 22         [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 23         public static extern IntPtr OpenService(IntPtr scHandle, string serviceName, int DesiredAccess);
 24 
 25         [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 26         public static extern bool CloseServiceHandle(IntPtr hSCObject);
 27 
 28         [DllImport("advapi32.dll")]
 29         public static extern IntPtr LockServiceDatabase(IntPtr hSCManager);
 30 
 31         [DllImport("advapi32.dll")]
 32         public static extern bool UnlockServiceDatabase(IntPtr hSCManager);
 33 
 34         [DllImport("kernel32.dll")]
 35         public static extern int GetLastError();
 36 
 37         [DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig2")]
 38         public static extern bool ChangeServiceFailureActions(IntPtr hService, int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_FAILURE_ACTIONS lpInfo);
 39 
 40         [DllImport("advapi32.dll")]
 41         public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, [MarshalAs(UnmanagedType.Struct)] ref TOKEN_PRIVILEGES NewState, int BufferLength, IntPtr PreviousState, ref int ReturnLength);
 42 
 43         [DllImport("advapi32.dll")]
 44         public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref long lpLuid);
 45 
 46         [DllImport("advapi32.dll")]
 47         public static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);
 48 
 49         [DllImport("kernel32.dll")]
 50         public static extern IntPtr GetCurrentProcess();
 51 
 52         [DllImport("kernel32.dll")]
 53         public static extern bool CloseHandle(IntPtr hndl);
 54         
 55         #endregion
 56 
 57         private const int TOKEN_ADJUST_PRIVILEGES = 32;
 58         private const int TOKEN_QUERY = 8;
 59         private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
 60         private const int SE_PRIVILEGE_ENABLED = 2;
 61 
 62         [StructLayout(LayoutKind.Sequential, Pack = 1)]
 63         public struct TOKEN_PRIVILEGES
 64         {
 65             public int PrivilegeCount;
 66             public LUID_AND_ATTRIBUTES Privileges;
 67         }
 68         [StructLayout(LayoutKind.Sequential)]
 69         public struct LUID_AND_ATTRIBUTES
 70         {
 71             public long Luid;
 72             public int Attributes;
 73         }
 74 
 75         [StructLayout(LayoutKind.Sequential)]
 76         public struct SERVICE_FAILURE_ACTIONS
 77         {
 78             /// <summary>
 79             /// 在此时间之后重置失败计数
 80             /// </summary>
 81             public int dwResetPeriod;
 82             public string lpRebootMsg;
 83             public string lpCommand;
 84             public int cActions;
 85             public int lpsaActions;
 86         }
 87 
 88         private const int SC_MANAGER_ALL_ACCESS = 0xF003F;
 89         private const int SERVICE_ALL_ACCESS = 0xF01FF;
 90         private const int SERVICE_CONFIG_DESCRIPTION = 0x1;
 91         private const int SERVICE_CONFIG_FAILURE_ACTIONS = 0x2;
 92         private const int ERROR_ACCESS_DENIED = 5;
 93         
 94         static string logMsgBase = "";
 95         static string ServiceName = "";
 96 
 97         public static void UpdateServiceConfig(string serviceName)
 98         {
 99             logMsgBase = "Windows 服务" + ServiceName + ":";
100             ServiceName = serviceName;
101             var FailureActions = new ArrayList();
102             
103             //第一次失败
104             FailureActions.Add(new FailureAction(RecoverAction.Restart, 0));
105             //第二次失败
106             FailureActions.Add(new FailureAction(RecoverAction.None, 0));
107             //后续失败
108             FailureActions.Add(new FailureAction(RecoverAction.Reboot, 0));
109 
110             int numActions = FailureActions.Count;
111 
112             IntPtr scmHndl = IntPtr.Zero;
113             IntPtr svcHndl = IntPtr.Zero;
114             IntPtr tmpBuf = IntPtr.Zero;
115             IntPtr svcLock = IntPtr.Zero;
116             
117             bool rslt = false;
118             try
119             {
120                 scmHndl = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
121                 if (scmHndl.ToInt32() <= 0)
122                 {
123                     LogInstallMessage(EventLogEntryType.Error, logMsgBase + "打开服务控制管理器失败");
124                     return;
125                 }
126                 svcLock = LockServiceDatabase(scmHndl);
127                 if (svcLock.ToInt32() <= 0)
128                 {
129 
130                     LogInstallMessage(EventLogEntryType.Error, logMsgBase + "无法锁定服务数据库进行写入");
131                     return;
132                 }
133                 svcHndl = OpenService(scmHndl, ServiceName, SERVICE_ALL_ACCESS);
134 
135                 if (svcHndl.ToInt32() <= 0)
136                 {
137                     LogInstallMessage(EventLogEntryType.Information, logMsgBase + "无法打开服务");
138                     return;
139                 }
140                 
141                     int[] actions = new int[numActions * 2];
142                     int currInd = 0;
143                     bool needShutdownPrivilege = false;
144                     foreach (FailureAction fa in FailureActions)
145                     {
146                         actions[currInd] = (int)fa.Type;
147                         actions[++currInd] = fa.Delay;
148                         currInd++;
149                         if (fa.Type == RecoverAction.Reboot)
150                         {
151                             needShutdownPrivilege = true;
152                         }
153                     }
154 
155                     if (needShutdownPrivilege)
156                     {
157                         rslt = GrandShutdownPrivilege();
158                         if (!rslt) return;
159                     }
160 
161                     tmpBuf = Marshal.AllocHGlobal(numActions * 8);
162                     Marshal.Copy(actions, 0, tmpBuf, numActions * 2);
163                     SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS();
164 
165                     sfa.cActions = numActions;
166                     sfa.dwResetPeriod = 0;
167                     sfa.lpCommand = "";
168                     sfa.lpRebootMsg = "";
169                     sfa.lpsaActions = tmpBuf.ToInt32();
170                 
171                     rslt = ChangeServiceFailureActions(svcHndl, SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa);
172                     if (!rslt)
173                     {
174                         int err = GetLastError();
175                         if (err == ERROR_ACCESS_DENIED)
176                         {
177                             throw new Exception(logMsgBase + "配置失败时恢复的操作失败");
178                         }
179                     }
180                     Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero;
181                     LogInstallMessage(EventLogEntryType.Information, logMsgBase + "已成功配置失败时恢复的操作");
182 
183             }
184             catch (Exception ex)
185             {
186                 LogInstallMessage(EventLogEntryType.Error, ex.Message);
187             }
188             finally
189             {
190                 if (scmHndl != IntPtr.Zero)
191                 {
192                     if (svcLock != IntPtr.Zero)
193                     {
194                         UnlockServiceDatabase(svcLock);
195                         svcLock = IntPtr.Zero;
196                     }
197                     CloseServiceHandle(scmHndl);
198                     scmHndl = IntPtr.Zero;
199                 }
200                 if (svcHndl != IntPtr.Zero)
201                 {
202                     CloseServiceHandle(svcHndl);
203                     svcHndl = IntPtr.Zero;
204                 }
205                 if (tmpBuf != IntPtr.Zero)
206                 {
207                     Marshal.FreeHGlobal(tmpBuf);
208                     tmpBuf = IntPtr.Zero;
209                 }
210             }
211 
212         }
213         
214         static bool GrandShutdownPrivilege()
215         {
216             bool retRslt = false;
217             IntPtr hToken = IntPtr.Zero;
218             IntPtr myProc = IntPtr.Zero;
219             TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();
220             long Luid = 0;
221             int retLen = 0;
222 
223             try
224             {
225 
226                 myProc = GetCurrentProcess();
227                 bool rslt = OpenProcessToken(myProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref hToken);
228                 if (!rslt) return retRslt;
229 
230                 LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref Luid);
231 
232                 tkp.PrivilegeCount = 1;
233                 tkp.Privileges.Luid = Luid;
234                 tkp.Privileges.Attributes = SE_PRIVILEGE_ENABLED;
235 
236                 rslt = AdjustTokenPrivileges(hToken, false, ref tkp, 0, IntPtr.Zero, ref retLen);
237 
238                 if (GetLastError() != 0)
239                 {
240                     throw new Exception("无法授予关机特权");
241                 }
242                 retRslt = true;
243             }
244             catch (Exception ex)
245             {
246                 LogInstallMessage(EventLogEntryType.Error, logMsgBase + ex.Message);
247             }
248             finally
249             {
250                 if (hToken != IntPtr.Zero)
251                 {
252                     CloseHandle(hToken);
253                 }
254             }
255             return retRslt;
256         }
257         
258         static void LogInstallMessage(EventLogEntryType logLevel, string msg)
259         {
260             try
261             {
262                 EventLog.WriteEntry(ServiceName, msg, logLevel);
263             }
264             catch
265             {
266                 
267             }
268         }
269 
270         enum RecoverAction
271         {
272             /// <summary>
273             /// 无操作
274             /// </summary>
275             None = 0, 
276             /// <summary>
277             /// 重新启动服务
278             /// </summary>
279             Restart = 1, 
280             /// <summary>
281             /// 重启计算机
282             /// </summary>
283             Reboot = 2, 
284             /// <summary>
285             /// 运行一个程序
286             /// </summary>
287             RunCommand = 3
288         }
289 
290         class FailureAction
291         {
292             private RecoverAction type = RecoverAction.None;
293             /// <summary>
294             /// 在此时间之后重新启动服务
295             /// </summary>
296             private int delay = 0;
297             public FailureAction()
298             {
299 
300             }
301             public FailureAction(RecoverAction actionType, int actionDelay)
302             {
303                 this.type = actionType;
304                 this.delay = actionDelay;
305             }
306 
307             public RecoverAction Type
308             {
309                 get { return type; }
310                 set { type = value; }
311             }
312             /// <summary>
313             /// 在此时间之后重新启动服务
314             /// </summary>
315             public int Delay
316             {
317                 get { return delay; }
318                 set { delay = value; }
319             }
320 
321         }
322     }

 

抱歉!评论已关闭.