calculator/internal/Calculator.UIAutomationLibrary/Utilities/ServiceHelper.cs
Howard Wolosky c13b8a099e Hello GitHub
2019-01-28 16:24:37 -08:00

157 lines
6.3 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Calculator.UIAutomationLibrary
{
public class ServiceHelper
{
public static void Start(string serviceName, int timeoutInMilliSeconds = 30000)
{
IntPtr hService = IntPtr.Zero;
IntPtr hSCManager = IntPtr.Zero;
try
{
hSCManager = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
if (IntPtr.Zero == hSCManager)
{
throw new Exception($"Start: Cannot Open OpenSCManager, {Marshal.GetLastWin32Error()}");
}
hService = NativeMethods.OpenService(hSCManager, serviceName, NativeMethods.SERVICE_ALL_ACCESS);
if (IntPtr.Zero == hService)
{
throw new Exception($"Start: Cannot Open Service, {Marshal.GetLastWin32Error()}");
}
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
{
throw new Exception($"Start: Unable to query status of Service, {Marshal.GetLastWin32Error()}");
}
if (serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_RUNNING &&
serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_START_PENDING)
{
if (!NativeMethods.StartService(hService, 0, null))
{
throw new Exception($"Start: Service cannot be started, {Marshal.GetLastWin32Error()}");
}
}
WaitForStatus(hService, NativeMethods.SERVICE_STATE.SERVICE_RUNNING, TimeSpan.FromMilliseconds(timeoutInMilliSeconds));
}
finally
{
if (IntPtr.Zero != hService)
{
NativeMethods.CloseServiceHandle(hService);
}
if (IntPtr.Zero != hSCManager)
{
NativeMethods.CloseServiceHandle(hSCManager);
}
}
}
public static void Stop(string serviceName, int timeoutInMilliSeconds = 30000)
{
IntPtr hSCManager = IntPtr.Zero;
IntPtr hService = IntPtr.Zero;
try
{
hSCManager = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
if (IntPtr.Zero == hSCManager)
{
throw new Exception($"Stop: Cannot Open OpenSCManager, {Marshal.GetLastWin32Error()}");
}
hService = NativeMethods.OpenService(hSCManager, serviceName, NativeMethods.SERVICE_ALL_ACCESS);
if (IntPtr.Zero == hService)
{
throw new Exception($"Stop: Cannot Open Service, {Marshal.GetLastWin32Error()}");
}
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
{
throw new Exception($"Stop: Unable to query status of Service, {Marshal.GetLastWin32Error()}");
}
if (serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_STOPPED &&
serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_STOP_PENDING)
{
if (!NativeMethods.ControlService(hService, NativeMethods.SERVICE_CONTROL.STOP, ref serviceStatus))
{
throw new Exception($"Stop: Service cannot be stopped, {Marshal.GetLastWin32Error()}");
}
}
WaitForStatus(hService, NativeMethods.SERVICE_STATE.SERVICE_STOPPED, TimeSpan.FromMilliseconds(timeoutInMilliSeconds));
}
finally
{
if (IntPtr.Zero != hService)
{
NativeMethods.CloseServiceHandle(hService);
}
if (IntPtr.Zero != hSCManager)
{
NativeMethods.CloseServiceHandle(hSCManager);
}
}
}
public static bool IsInstalled(string svcName)
{
IntPtr sc_handle = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
if (sc_handle == IntPtr.Zero)
{
throw new Exception($"IsInstalled: Cannot open service manager, {Marshal.GetLastWin32Error()}");
}
bool bResult = false;
IntPtr sv_handle = NativeMethods.OpenService(sc_handle, svcName, NativeMethods.SERVICE_QUERY_CONFIG);
if (sv_handle.ToInt64() != 0)
{
bResult = true;
NativeMethods.CloseServiceHandle(sv_handle);
}
NativeMethods.CloseServiceHandle(sc_handle);
return bResult;
}
private static void WaitForStatus(IntPtr hService, NativeMethods.SERVICE_STATE desiredStatus, TimeSpan timeout)
{
Stopwatch swLoop = new Stopwatch();
swLoop.Start();
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
do
{
Thread.Sleep(500);
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
{
throw new Exception($"WaitForStatus: Unable to query status of service, {Marshal.GetLastWin32Error()}");
}
}
while (serviceStatus.dwCurrentState != (int)desiredStatus && (swLoop.ElapsedMilliseconds <= timeout.TotalMilliseconds));
if (serviceStatus.dwCurrentState != (int)desiredStatus)
{
throw new Exception($"WaitForStatus: Service failed to reach desired state: {desiredStatus}, current state: {serviceStatus.dwCurrentState}");
}
}
}
}