• window service 恢复选项卡设置


      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     }
  • 相关阅读:
    史上最全Html与CSS布局技巧
    Discuz! X的CSS加载机制
    关于input框只能输入纯数字问题
    对象的数据属性
    vue中将光标定位到Input上的问题
    端口占用问题解决方案
    el-button如何消除右边计数样式
    如何改变vscode的背景颜色
    为什么——要实例化对象?
    call()&apply()
  • 原文地址:https://www.cnblogs.com/94cool/p/2931710.html
Copyright © 2020-2023  润新知