как отложить выключение и запустить процесс в службе windows

Я должен запустить процесс, то есть приложение при выключении Windows, есть ли какой-нибудь способ отложить выключение Windows и запустить приложение в службе windows …

protected override void OnShutdown() { // Add your save code here // Add your save code here StreamWriter str = new StreamWriter("D:\\Log.txt", true); str.WriteLine("Service stoped due to on" + DateTime.Now.ToString()); str.Close(); base.OnShutdown(); } 

Я использовал функцию выше, которая отменяет завершение работы, и я смог записать запись в текстовый файл, но после этого я не смог запустить приложение. В поиске я обнаружил, что задержка была ниже, чем через несколько секунд после выключения пользователя

this.RequestAdditionalTime (250000);

это дает дополнительную задержку времени на 25 секунд при событии отключения, но я не смог запустить приложение. Может ли кто-нибудь предложить метод или идеи для запуска приложения при завершении работы.

Возможность приложений блокировать отложенное завершение работы системы была строго ограничена в Windows Vista. Подробности обобщены в двух удобных статьях в MSDN: « Отключение изменений для Windows Vista» и « Отключение приложений» в Windows Vista .

Как указано на этой странице, вы не должны полагаться на возможность блокировать выключение на срок дольше 5 секунд. Если вы хотите заблокировать ожидающее событие завершения работы, ваше приложение должно использовать новую функцию ShutdownBlockReasonCreate , которая позволяет вам зарегистрировать строку, которая объясняет пользователю причину, по которой вы считаете, что остановка должна быть заблокирована. Пользователь оставляет за собой возможность прислушаться к вашим советам и отменить выключение, или бросить осторожность на ветер и отменить в любом случае.

Как только ваша заявка закончит делать то, что она не должна прерывать, вы должны вызвать соответствующую функцию ShutdownBlockReasonDestroy , которая освобождает строку причины и указывает, что система теперь может быть отключена.

Также помните, что службы Windows теперь работают в изолированном сеансе и им запрещено взаимодействовать с пользователем. Мой ответ здесь также дает более подробную информацию, а также красивую диаграмму.

В принципе, это невозможно. Windows собирается сразиться с вами за зуб и гвоздь, запустив отдельный процесс с вашего Сервиса, а также любую попытку сделать блокировку ожидающего завершения работы. В конечном счете, пользователь имеет право переопределять все, что вы пытаетесь извлечь. Это звучит как-то, что вы должны решить с помощью политик безопасности, а не с вопросом-спросите об этом на сервере .

В Windows Vista с пакетом обновления 1 и выше доступно новое SERVICE_CONTROL_PRESHUTDOWN. К сожалению, он еще не поддерживается платформой .NET, но обходным путем является использование рефлексии. Просто наследуйте свой class обслуживания из ServicePreshutdownBase , переопределите OnStop и периодически вызывайте RequestAdditionalTime() . Обратите внимание, что для параметра CanShutdown должно быть установлено значение false .

 public class ServicePreshutdownBase : ServiceBase { public bool Preshutdown { get; private set; } public ServicePreshutdownBase() { Version versionWinVistaSp1 = new Version(6, 0, 6001); if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version >= versionWinVistaSp1) { var acceptedCommandsField = typeof (ServiceBase).GetField("acceptedCommands", BindingFlags.Instance | BindingFlags.NonPublic); if (acceptedCommandsField == null) throw new InvalidOperationException("Private field acceptedCommands not found on ServiceBase"); int acceptedCommands = (int) acceptedCommandsField.GetValue(this); acceptedCommands |= 0x00000100; //SERVICE_ACCEPT_PRESHUTDOWN; acceptedCommandsField.SetValue(this, acceptedCommands); } } protected override void OnCustomCommand(int command) { // command is SERVICE_CONTROL_PRESHUTDOWN if (command == 0x0000000F) { var baseCallback = typeof(ServiceBase).GetMethod("ServiceCommandCallback", BindingFlags.Instance | BindingFlags.NonPublic); if (baseCallback == null) throw new InvalidOperationException("Private method ServiceCommandCallback not found on ServiceBase"); try { Preshutdown = true; //now pretend stop was called 0x00000001 baseCallback.Invoke(this, new object[] {0x00000001}); } finally { Preshutdown = false; } } } } 

Вот пример использования:

 public partial class Service1 : ServicePreshutdownBase { public Service1() { InitializeComponent(); this.CanShutdown = false; } protected override void OnStop() { WriteLog(Preshutdown ? "Service OnPreshutdown" : "Service OnStop"); for (int i = 0; i < 180; i++) { Thread.Sleep(1000); WriteLog("Service stop in progress..."); RequestAdditionalTime(2000); } WriteLog(Preshutdown ? "Service preshutdown completed" : "Service stop completed"); } } 

Это будет работать в течение 3 минут 20 секунд, если вам нужно больше времени, тогда вам нужно настроить службу. Лучшее место для этого - во время установки. Просто используйте ServicePreshutdownInstaller вместо ServiceInstaller и установите PreshutdownTimeout на максимальное время, которое вам когда-либо понадобится.

 public class ServicePreshutdownInstaller : ServiceInstaller { private int _preshutdownTimeout = 200000; ///  /// Gets or sets the preshutdown timeout for the service. ///  /// ///  /// The preshutdown timeout of the service. The default is 200000ms (200s). ///  [DefaultValue(200000)] [ServiceProcessDescription("ServiceInstallerPreshutdownTimeout")] public int PreshutdownTimeout { get { return _preshutdownTimeout; } set { _preshutdownTimeout = value; } } public override void Install(System.Collections.IDictionary stateSaver) { base.Install(stateSaver); Version versionWinVistaSp1 = new Version(6, 0, 6001); if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version < versionWinVistaSp1) { //Preshutdown is not supported return; } Context.LogMessage(string.Format("Setting preshutdown timeout {0}ms to service {1}", PreshutdownTimeout, ServiceName)); IntPtr service = IntPtr.Zero; IntPtr sCManager = IntPtr.Zero; try { // Open the service control manager sCManager = OpenSCManager(null, null, ServiceControlAccessRights.SC_MANAGER_CONNECT); if (sCManager == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to open Service Control Manager."); // Open the service service = OpenService(sCManager, ServiceName, ServiceAccessRights.SERVICE_CHANGE_CONFIG); if (service == IntPtr.Zero) throw new Win32Exception(); // Set up the preshutdown timeout structure SERVICE_PRESHUTDOWN_INFO preshutdownInfo = new SERVICE_PRESHUTDOWN_INFO(); preshutdownInfo.dwPreshutdownTimeout = (uint)_preshutdownTimeout; // Make the change int changeResult = ChangeServiceConfig2( service, ServiceConfig2InfoLevel.SERVICE_CONFIG_PRESHUTDOWN_INFO, ref preshutdownInfo); // Check that the change occurred if (changeResult == 0) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to change the Service configuration."); } Context.LogMessage(string.Format("Preshutdown timeout {0}ms set to service {1}", PreshutdownTimeout, ServiceName)); } finally { // Clean up if (service != IntPtr.Zero)CloseServiceHandle(service); if (sCManager != IntPtr.Zero)Marshal.FreeHGlobal(sCManager); } } [StructLayout(LayoutKind.Sequential)] public struct SERVICE_PRESHUTDOWN_INFO { public UInt32 dwPreshutdownTimeout; } [Flags] public enum ServiceControlAccessRights : int { SC_MANAGER_CONNECT = 0x0001, // Required to connect to the service control manager. SC_MANAGER_CREATE_SERVICE = 0x0002, // Required to call the CreateService function to create a service object and add it to the database. SC_MANAGER_ENUMERATE_SERVICE = 0x0004, // Required to call the EnumServicesStatusEx function to list the services that are in the database. SC_MANAGER_LOCK = 0x0008, // Required to call the LockServiceDatabase function to acquire a lock on the database. SC_MANAGER_QUERY_LOCK_STATUS = 0x0010, // Required to call the QueryServiceLockStatus function to retrieve the lock status information for the database SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020, // Required to call the NotifyBootConfigStatus function. SC_MANAGER_ALL_ACCESS = 0xF003F // Includes STANDARD_RIGHTS_REQUIRED, in addition to all access rights in this table. } [Flags] public enum ServiceAccessRights : int { SERVICE_QUERY_CONFIG = 0x0001, // Required to call the QueryServiceConfig and QueryServiceConfig2 functions to query the service configuration. SERVICE_CHANGE_CONFIG = 0x0002, // Required to call the ChangeServiceConfig or ChangeServiceConfig2 function to change the service configuration. Because this grants the caller the right to change the executable file that the system runs, it should be granted only to administrators. SERVICE_QUERY_STATUS = 0x0004, // Required to call the QueryServiceStatusEx function to ask the service control manager about the status of the service. SERVICE_ENUMERATE_DEPENDENTS = 0x0008, // Required to call the EnumDependentServices function to enumerate all the services dependent on the service. SERVICE_START = 0x0010, // Required to call the StartService function to start the service. SERVICE_STOP = 0x0020, // Required to call the ControlService function to stop the service. SERVICE_PAUSE_CONTINUE = 0x0040, // Required to call the ControlService function to pause or continue the service. SERVICE_INTERROGATE = 0x0080, // Required to call the ControlService function to ask the service to report its status immediately. SERVICE_USER_DEFINED_CONTROL = 0x0100, // Required to call the ControlService function to specify a user-defined control code. SERVICE_ALL_ACCESS = 0xF01FF // Includes STANDARD_RIGHTS_REQUIRED in addition to all access rights in this table. } public enum ServiceConfig2InfoLevel : int { SERVICE_CONFIG_DESCRIPTION = 0x00000001, // The lpBuffer parameter is a pointer to a SERVICE_DESCRIPTION structure. SERVICE_CONFIG_FAILURE_ACTIONS = 0x00000002, // The lpBuffer parameter is a pointer to a SERVICE_FAILURE_ACTIONS structure. SERVICE_CONFIG_PRESHUTDOWN_INFO = 0x00000007 // The lpBuffer parameter is a pointer to a SERVICE_PRESHUTDOWN_INFO structure. } [DllImport("advapi32.dll", EntryPoint = "OpenSCManager")] public static extern IntPtr OpenSCManager( string machineName, string databaseName, ServiceControlAccessRights desiredAccess); [DllImport("advapi32.dll", EntryPoint = "CloseServiceHandle")] public static extern int CloseServiceHandle(IntPtr hSCObject); [DllImport("advapi32.dll", EntryPoint = "OpenService")] public static extern IntPtr OpenService( IntPtr hSCManager, string serviceName, ServiceAccessRights desiredAccess); [DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig2")] public static extern int ChangeServiceConfig2( IntPtr hService, ServiceConfig2InfoLevel dwInfoLevel, ref SERVICE_PRESHUTDOWN_INFO lpInfo); } 

У меня есть аналогичная проблема , и есть один трюк, который может работать в вашем случае. Вы можете запустить приложение, о котором идет речь, прежде чем выключение начнется с флага CREATE_SUSPENDED (см. Это ). Это гарантирует, что процесс будет создан, но никогда не будет запущен. При выключении вы можете возобновить этот процесс, и он будет продолжен с выполнением.

Обратите внимание, что возможно, что процесс не сможет инициализировать и запустить в любом случае, так как во время выключения некоторые функции ОС будут терпеть неудачу.

Еще одно следствие: процесс, который должен запускаться при завершении работы, будет отображаться в диспетчере задач. Можно было бы убить этот процесс.

Вот статья о Shutdown Event Tracker. Вы можете активировать его в Windows XP. Он запрашивает у пользователя причину остановки.

пространство имен WindowsService1 {[StructLayout (LayoutKind.Sequential)] public struct SERVICE_STATUS {public int serviceType; public int currentState; public int controlsAccepted; public int win32ExitCode; public int serviceSpecificExitCode; public int checkPoint; public int waitHint; }

 public enum SERVICE_STATE : uint { SERVICE_STOPPED = 0x00000001, SERVICE_START_PENDING = 0x00000002, SERVICE_STOP_PENDING = 0x00000003, SERVICE_RUNNING = 0x00000004, SERVICE_CONTINUE_PENDING = 0x00000005, SERVICE_PAUSE_PENDING = 0x00000006, SERVICE_PAUSED = 0x00000007 } public enum ControlsAccepted { ACCEPT_STOP = 1, ACCEPT_PAUSE_CONTINUE = 2, ACCEPT_SHUTDOWN = 4, ACCEPT_PRESHUTDOWN = 0xf, ACCEPT_POWER_EVENT = 64, ACCEPT_SESSION_CHANGE = 128 } [Flags] public enum SERVICE_CONTROL : uint { STOP = 0x00000001, PAUSE = 0x00000002, CONTINUE = 0x00000003, INTERROGATE = 0x00000004, SHUTDOWN = 0x00000005, PARAMCHANGE = 0x00000006, NETBINDADD = 0x00000007, NETBINDREMOVE = 0x00000008, NETBINDENABLE = 0x00000009, NETBINDDISABLE = 0x0000000A, DEVICEEVENT = 0x0000000B, HARDWAREPROFILECHANGE = 0x0000000C, POWEREVENT = 0x0000000D, SESSIONCHANGE = 0x0000000E } public enum INFO_LEVEL : uint { SERVICE_CONFIG_DESCRIPTION = 0x00000001, SERVICE_CONFIG_FAILURE_ACTIONS = 0x00000002, SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 0x00000003, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 0x00000004, SERVICE_CONFIG_SERVICE_SID_INFO = 0x00000005, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 0x00000006, SERVICE_CONFIG_PRESHUTDOWN_INFO = 0x00000007, SERVICE_CONFIG_TRIGGER_INFO = 0x00000008, SERVICE_CONFIG_PREFERRED_NODE = 0x00000009 } [StructLayout(LayoutKind.Sequential)] public struct SERVICE_PRESHUTDOWN_INFO { public UInt32 dwPreshutdownTimeout; } [Flags] public enum SERVICE_ACCESS : uint { STANDARD_RIGHTS_REQUIRED = 0xF0000, SERVICE_QUERY_CONFIG = 0x00001, SERVICE_CHANGE_CONFIG = 0x00002, SERVICE_QUERY_STATUS = 0x00004, SERVICE_ENUMERATE_DEPENDENTS = 0x00008, SERVICE_START = 0x00010, SERVICE_STOP = 0x00020, SERVICE_PAUSE_CONTINUE = 0x00040, SERVICE_INTERROGATE = 0x00080, SERVICE_USER_DEFINED_CONTROL = 0x00100, SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL) } [Flags] public enum SCM_ACCESS : uint { STANDARD_RIGHTS_REQUIRED = 0xF0000, SC_MANAGER_CONNECT = 0x00001, SC_MANAGER_CREATE_SERVICE = 0x00002, SC_MANAGER_ENUMERATE_SERVICE = 0x00004, SC_MANAGER_LOCK = 0x00008, SC_MANAGER_QUERY_LOCK_STATUS = 0x00010, SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00020, SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS | SC_MANAGER_MODIFY_BOOT_CONFIG } public partial class Service1 : ServiceBase { [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); [DllImport("advapi32.dll")] internal static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, IntPtr lpInfo); [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); const int SERVICE_ACCEPT_PRESHUTDOWN = 0x100; const int SERVICE_CONTROL_PRESHUTDOWN = 0xf; public Service1() { InitializeComponent(); CanShutdown = true; tim = new Timer(); tim.Interval = 5000; tim.Elapsed += tim_Elapsed; FieldInfo acceptedCommandsFieldInfo = typeof(ServiceBase).GetField("acceptedCommands", BindingFlags.Instance | BindingFlags.NonPublic); int value = (int)acceptedCommandsFieldInfo.GetValue(this); acceptedCommandsFieldInfo.SetValue(this, value | SERVICE_ACCEPT_PRESHUTDOWN); StreamWriter writer = new StreamWriter("D:\\LogConst.txt", true); try { IntPtr hMngr = OpenSCManager("localhost", null, (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS); IntPtr hSvc = OpenService(hMngr, "WindowsService1", (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS); SERVICE_PRESHUTDOWN_INFO spi = new SERVICE_PRESHUTDOWN_INFO(); spi.dwPreshutdownTimeout = 5000; IntPtr lpInfo = Marshal.AllocHGlobal(Marshal.SizeOf(spi)); if (lpInfo == IntPtr.Zero) { writer.WriteLine(String.Format("Unable to allocate memory for service action, error was: 0x{0:X} -- {1}", Marshal.GetLastWin32Error(), DateTime.Now.ToLongTimeString())); } Marshal.StructureToPtr(spi, lpInfo, false); // apply the new timeout value if (!ChangeServiceConfig2(hSvc, (int)INFO_LEVEL.SERVICE_CONFIG_PRESHUTDOWN_INFO, lpInfo)) writer.WriteLine(DateTime.Now.ToLongTimeString() + " Failed to change service timeout"); else writer.WriteLine(DateTime.Now.ToLongTimeString() + " change service timeout : " + spi.dwPreshutdownTimeout); } catch (Exception ex) { writer.WriteLine(DateTime.Now.ToLongTimeString() + " " + ex.Message); } writer.Close(); } void tim_Elapsed(object sender, ElapsedEventArgs e) { result = false; StreamWriter writer = new StreamWriter("D:\\hede.txt", true); writer.WriteLine(DateTime.Now.ToLongTimeString()); //System.Threading.Thread.Sleep(5000); writer.Close(); result = true; tim.Stop(); } Timer tim; bool result = false; protected override void OnStart(string[] args) { RequestAdditionalTime(1000); tim.Start(); } protected override void OnStop() { } protected override void OnCustomCommand(int command) { StreamWriter writer = new StreamWriter("D:\\Log.txt", true); try { if (command == SERVICE_CONTROL_PRESHUTDOWN) { int checkpoint = 1; writer.WriteLine(DateTime.Now.ToLongTimeString()); while (!result) { SERVICE_STATUS myServiceStatus = new SERVICE_STATUS(); myServiceStatus.currentState = (int)SERVICE_STATE.SERVICE_STOP_PENDING; myServiceStatus.serviceType = 16; myServiceStatus.serviceSpecificExitCode = 0; myServiceStatus.checkPoint = checkpoint; SetServiceStatus(this.ServiceHandle, ref myServiceStatus); checkpoint++; } writer.WriteLine(DateTime.Now.ToLongTimeString()); } } catch (Exception ex) { writer.WriteLine(DateTime.Now.ToLongTimeString() + " " + ex.Message); } writer.Close(); base.OnCustomCommand(command); } } - public enum SERVICE_STATE : uint { SERVICE_STOPPED = 0x00000001, SERVICE_START_PENDING = 0x00000002, SERVICE_STOP_PENDING = 0x00000003, SERVICE_RUNNING = 0x00000004, SERVICE_CONTINUE_PENDING = 0x00000005, SERVICE_PAUSE_PENDING = 0x00000006, SERVICE_PAUSED = 0x00000007 } public enum ControlsAccepted { ACCEPT_STOP = 1, ACCEPT_PAUSE_CONTINUE = 2, ACCEPT_SHUTDOWN = 4, ACCEPT_PRESHUTDOWN = 0xf, ACCEPT_POWER_EVENT = 64, ACCEPT_SESSION_CHANGE = 128 } [Flags] public enum SERVICE_CONTROL : uint { STOP = 0x00000001, PAUSE = 0x00000002, CONTINUE = 0x00000003, INTERROGATE = 0x00000004, SHUTDOWN = 0x00000005, PARAMCHANGE = 0x00000006, NETBINDADD = 0x00000007, NETBINDREMOVE = 0x00000008, NETBINDENABLE = 0x00000009, NETBINDDISABLE = 0x0000000A, DEVICEEVENT = 0x0000000B, HARDWAREPROFILECHANGE = 0x0000000C, POWEREVENT = 0x0000000D, SESSIONCHANGE = 0x0000000E } public enum INFO_LEVEL : uint { SERVICE_CONFIG_DESCRIPTION = 0x00000001, SERVICE_CONFIG_FAILURE_ACTIONS = 0x00000002, SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 0x00000003, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 0x00000004, SERVICE_CONFIG_SERVICE_SID_INFO = 0x00000005, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 0x00000006, SERVICE_CONFIG_PRESHUTDOWN_INFO = 0x00000007, SERVICE_CONFIG_TRIGGER_INFO = 0x00000008, SERVICE_CONFIG_PREFERRED_NODE = 0x00000009 } [StructLayout(LayoutKind.Sequential)] public struct SERVICE_PRESHUTDOWN_INFO { public UInt32 dwPreshutdownTimeout; } [Flags] public enum SERVICE_ACCESS : uint { STANDARD_RIGHTS_REQUIRED = 0xF0000, SERVICE_QUERY_CONFIG = 0x00001, SERVICE_CHANGE_CONFIG = 0x00002, SERVICE_QUERY_STATUS = 0x00004, SERVICE_ENUMERATE_DEPENDENTS = 0x00008, SERVICE_START = 0x00010, SERVICE_STOP = 0x00020, SERVICE_PAUSE_CONTINUE = 0x00040, SERVICE_INTERROGATE = 0x00080, SERVICE_USER_DEFINED_CONTROL = 0x00100, SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_USER_DEFINED_CONTROL) } [Flags] public enum SCM_ACCESS : uint { STANDARD_RIGHTS_REQUIRED = 0xF0000, SC_MANAGER_CONNECT = 0x00001, SC_MANAGER_CREATE_SERVICE = 0x00002, SC_MANAGER_ENUMERATE_SERVICE = 0x00004, SC_MANAGER_LOCK = 0x00008, SC_MANAGER_QUERY_LOCK_STATUS = 0x00010, SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00020, SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS | SC_MANAGER_MODIFY_BOOT_CONFIG } public partial class Service1 : ServiceBase { [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); [DllImport("advapi32.dll")] internal static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, IntPtr lpInfo); [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); const int SERVICE_ACCEPT_PRESHUTDOWN = 0x100; const int SERVICE_CONTROL_PRESHUTDOWN = 0xf; public Service1() { InitializeComponent(); CanShutdown = true; tim = new Timer(); tim.Interval = 5000; tim.Elapsed += tim_Elapsed; FieldInfo acceptedCommandsFieldInfo = typeof(ServiceBase).GetField("acceptedCommands", BindingFlags.Instance | BindingFlags.NonPublic); int value = (int)acceptedCommandsFieldInfo.GetValue(this); acceptedCommandsFieldInfo.SetValue(this, value | SERVICE_ACCEPT_PRESHUTDOWN); StreamWriter writer = new StreamWriter("D:\\LogConst.txt", true); try { IntPtr hMngr = OpenSCManager("localhost", null, (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS); IntPtr hSvc = OpenService(hMngr, "WindowsService1", (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS); SERVICE_PRESHUTDOWN_INFO spi = new SERVICE_PRESHUTDOWN_INFO(); spi.dwPreshutdownTimeout = 5000; IntPtr lpInfo = Marshal.AllocHGlobal(Marshal.SizeOf(spi)); if (lpInfo == IntPtr.Zero) { writer.WriteLine(String.Format("Unable to allocate memory for service action, error was: 0x{0:X} -- {1}", Marshal.GetLastWin32Error(), DateTime.Now.ToLongTimeString())); } Marshal.StructureToPtr(spi, lpInfo, false); // apply the new timeout value if (!ChangeServiceConfig2(hSvc, (int)INFO_LEVEL.SERVICE_CONFIG_PRESHUTDOWN_INFO, lpInfo)) writer.WriteLine(DateTime.Now.ToLongTimeString() + " Failed to change service timeout"); else writer.WriteLine(DateTime.Now.ToLongTimeString() + " change service timeout : " + spi.dwPreshutdownTimeout); } catch (Exception ex) { writer.WriteLine(DateTime.Now.ToLongTimeString() + " " + ex.Message); } writer.Close(); } void tim_Elapsed(object sender, ElapsedEventArgs e) { result = false; StreamWriter writer = new StreamWriter("D:\\hede.txt", true); writer.WriteLine(DateTime.Now.ToLongTimeString()); //System.Threading.Thread.Sleep(5000); writer.Close(); result = true; tim.Stop(); } Timer tim; bool result = false; protected override void OnStart(string[] args) { RequestAdditionalTime(1000); tim.Start(); } protected override void OnStop() { } protected override void OnCustomCommand(int command) { StreamWriter writer = new StreamWriter("D:\\Log.txt", true); try { if (command == SERVICE_CONTROL_PRESHUTDOWN) { int checkpoint = 1; writer.WriteLine(DateTime.Now.ToLongTimeString()); while (!result) { SERVICE_STATUS myServiceStatus = new SERVICE_STATUS(); myServiceStatus.currentState = (int)SERVICE_STATE.SERVICE_STOP_PENDING; myServiceStatus.serviceType = 16; myServiceStatus.serviceSpecificExitCode = 0; myServiceStatus.checkPoint = checkpoint; SetServiceStatus(this.ServiceHandle, ref myServiceStatus); checkpoint++; } writer.WriteLine(DateTime.Now.ToLongTimeString()); } } catch (Exception ex) { writer.WriteLine(DateTime.Now.ToLongTimeString() + " " + ex.Message); } writer.Close(); base.OnCustomCommand(command); } } 

}

  • Кнопка закрытия в tabControl
  • Как найти элемент управления, который я добавил в форму?
  • Как получить доступ к элементу управления из статического метода?
  • Узнайте о контроле с последним фокусом
  • Модель-View-Presenter в WinForms
  • Как я могу сделать что-то, что ловит все «необработанные» исключения в приложении WinForms?
  • DataGridView с использованием SortableBindingList
  • Остановите «Дин» при нажатии Enter
  • Как настроить приложение для правильной работы на машине с высокой настройкой DPI (например, 150%)?
  • Как определить текущую нажатую клавишу?
  • Как пользователь может изменять размер управления во время выполнения в winforms
  • Давайте будем гением компьютера.