my first shot

pull/18/head
Kohsuke Kawaguchi 2013-04-20 17:04:57 -07:00
parent 8c2f65f55a
commit 4caa17f921
4 changed files with 262 additions and 142 deletions

View File

@ -2,16 +2,17 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.ComponentModel;
namespace Advapi32 namespace Advapi32
{ {
class ServiceManager class ServiceManager : IDisposable
{ {
private IntPtr Handle; private IntPtr Handle;
public ServiceManager() public ServiceManager()
{ {
Handle = Advapi32.OpenSCManager(null, null, (uint)Advapi32.SCM_ACCESS.SC_MANAGER_ALL_ACCESS); Handle = Advapi32.OpenSCManager(null, null, (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
if (Handle == IntPtr.Zero) if (Handle == IntPtr.Zero)
{ {
throw new Exception(String.Format("Error connecting to Service Control Manager. Error provided was: 0x{0:X}", Marshal.GetLastWin32Error())); throw new Exception(String.Format("Error connecting to Service Control Manager. Error provided was: 0x{0:X}", Marshal.GetLastWin32Error()));
@ -20,22 +21,24 @@ namespace Advapi32
public Service Open(string serviceName) public Service Open(string serviceName)
{ {
IntPtr svcHandle = Advapi32.OpenService(Handle, serviceName, (int)Advapi32.SERVICE_ACCESS.SERVICE_ALL_ACCESS); IntPtr svcHandle = Advapi32.OpenService(Handle, serviceName, (int)SERVICE_ACCESS.SERVICE_ALL_ACCESS);
if (svcHandle == IntPtr.Zero) if (svcHandle == IntPtr.Zero)
{ {
throw new Exception(String.Format("Error opening service for modifying. Error returned was: 0x{0:X}", Marshal.GetLastWin32Error())); throw new Exception(String.Format("Error opening service for modifying. Error returned was: 0x{0:X}", Marshal.GetLastWin32Error()));
} }
Console.WriteLine("Opened " + serviceName);
return new Service(svcHandle); return new Service(svcHandle);
} }
public void Dispose() public void Dispose()
{ {
if (Handle != IntPtr.Zero)
Advapi32.CloseServiceHandle(Handle); Advapi32.CloseServiceHandle(Handle);
Handle = IntPtr.Zero; Handle = IntPtr.Zero;
} }
} }
class Service class Service : IDisposable
{ {
internal IntPtr Handle; internal IntPtr Handle;
@ -44,7 +47,50 @@ namespace Advapi32
Handle = service; Handle = service;
} }
public void ChangeConfig(TimeSpan failureResetPeriod)
{
SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS();
sfa.dwResetPeriod = failureResetPeriod.Seconds;
sfa.lpRebootMsg = ""; // delete message
sfa.lpCommand = ""; // delete the command to run
sfa.cActions = 0;
SC_ACTION[] lpsaActions = new SC_ACTION[2];
lpsaActions[0] = new SC_ACTION(SC_ACTION_TYPE.SC_ACTION_RESTART, 1000);
lpsaActions[1] = new SC_ACTION(SC_ACTION_TYPE.SC_ACTION_RESTART, 2000);
lpsaActions[1] = new SC_ACTION(SC_ACTION_TYPE.SC_ACTION_RESTART, 5000);
sfa.lpsaActions = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(SC_ACTION)) * 2);
try
{
for (int i = 0; i < lpsaActions.Length; i++)
{
Marshal.StructureToPtr(lpsaActions[i], sfa.lpsaActions/* new IntPtr(sfa.lpsaActions.ToInt64() + i * Marshal.SizeOf(typeof(SC_ACTION)))*/, false);
}
Console.WriteLine("Changing config to 2: sizeof(x)"+Marshal.SizeOf(typeof(SC_ACTION)));
int x = Marshal.GetLastWin32Error();
sfa.lpsaActions = IntPtr.Zero;
if (!Advapi32.ChangeServiceConfig2(Handle, SERVICE_CONFIG_INFOLEVEL.SERVICE_CONFIG_FAILURE_ACTIONS, sfa))
throw new Exception("Failed to change the failure actions", new Win32Exception());
throw new Exception("OK:" + x + "/" + Marshal.GetLastWin32Error(), new Win32Exception());
}
finally
{
Marshal.FreeCoTaskMem(sfa.lpsaActions);
}
}
public void Dispose()
{
if (Handle!=IntPtr.Zero)
Advapi32.CloseServiceHandle(Handle);
Handle = IntPtr.Zero;
}
} }
/// <summary> /// <summary>
@ -55,7 +101,11 @@ namespace Advapi32
{ {
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, IntPtr lpInfo); internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, IntPtr lpInfo);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ChangeServiceConfig2(IntPtr hService, SERVICE_CONFIG_INFOLEVEL dwInfoLevel, SERVICE_FAILURE_ACTIONS sfa);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); internal static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
@ -66,6 +116,8 @@ namespace Advapi32
[DllImport("advapi32.dll", SetLastError = true)] [DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseServiceHandle(IntPtr hSCObject); internal static extern bool CloseServiceHandle(IntPtr hSCObject);
}
internal enum SCM_ACCESS : uint internal enum SCM_ACCESS : uint
{ {
@ -204,5 +256,60 @@ namespace Advapi32
WINSTA_ALL_ACCESS = 0x0000037f WINSTA_ALL_ACCESS = 0x0000037f
} }
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms685126(v=vs.85).aspx
[StructLayout(LayoutKind.Sequential)]
public struct SC_ACTION
{
public SC_ACTION_TYPE Type;
/// <summary>
/// The time to wait before performing the specified action, in milliseconds.
/// </summary>
public uint Delay;
public SC_ACTION(SC_ACTION_TYPE type, uint delay)
{
this.Type = type;
this.Delay = delay;
}
}
internal enum SERVICE_CONFIG_INFOLEVEL
{
SERVICE_CONFIG_DESCRIPTION = 1,
SERVICE_CONFIG_FAILURE_ACTIONS = 2,
SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3,
SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4,
SERVICE_CONFIG_SERVICE_SID_INFO = 5,
SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6,
SERVICE_CONFIG_PRESHUTDOWN_INFO = 7,
SERVICE_CONFIG_TRIGGER_INFO = 8,
SERVICE_CONFIG_PREFERRED_NODE = 9
}
public enum SC_ACTION_TYPE
{
SC_ACTION_NONE = 0,
SC_ACTION_RESTART = 1,
SC_ACTION_REBOOT = 2,
SC_ACTION_RUN_COMMAND = 3
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms685939(v=vs.85).aspx
[StructLayout(LayoutKind.Sequential)]
public struct SERVICE_FAILURE_ACTIONS
{
/// <summary>
/// The time after which to reset the failure count to zero if there are no failures, in seconds.
/// Specify INFINITE to indicate that this value should never be reset.
/// </summary>
public int dwResetPeriod;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpRebootMsg;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpCommand;
public int cActions;
public IntPtr/*SC_ACTION[]*/ lpsaActions;
} }
} }

12
Main.cs
View File

@ -421,7 +421,7 @@ namespace winsw
}); });
} }
public static int Main(string[] args) public static int _Main(string[] args)
{ {
try try
{ {
@ -550,6 +550,16 @@ namespace winsw
else else
Console.WriteLine("Stopped"); Console.WriteLine("Stopped");
} }
if (args[0] == "autorestart")
{// debug only. to be removed.
using (Advapi32.ServiceManager scm = new Advapi32.ServiceManager())
{
using (Advapi32.Service sc = scm.Open(d.Id))
{
sc.ChangeConfig(TimeSpan.FromHours(48));
}
}
}
if (args[0] == "test") if (args[0] == "test")
{ {
WrapperService wsvc = new WrapperService(); WrapperService wsvc = new WrapperService();

View File

@ -53,9 +53,11 @@ namespace WMI
Win32Service Select(string name); Win32Service Select(string name);
} }
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa394418(v=vs.85).aspx
public interface Win32Service : IWmiObject public interface Win32Service : IWmiObject
{ {
string Description { get; set; } string Description { get; set; }
string Name { get; }
bool Started { get; } bool Started { get; }
void Delete(); void Delete();
void StartService(); void StartService();

View File

@ -53,6 +53,7 @@
<Compile Include="Main.cs"> <Compile Include="Main.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="NotGettingAnywhere.cs" />
<Compile Include="PeriodicRollingCalendar.cs" /> <Compile Include="PeriodicRollingCalendar.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceDescriptor.cs" /> <Compile Include="ServiceDescriptor.cs" />