Service implementation for Windows Threshold Mobile
Services are controlled by Service Control
Manager as in the Desktop Version. But for Mobile Threshold need to be compiled
with and liked with the libraries (Mincore.lib) as mentioned in an
Essential components of a service:
We should use mincore library for
creating and deploy service in Threshold platform. So that I’m creating wrapper
class in c which is used to communicate from c# application
To Implement the below
functionality in “Windows Service” wrapper project
Step1: Create instance for
“service controller manager “which is used control our windows service like
create, start, stop, restart and delete.
SC_HANDLE OpenServiceControlManager()
{
SC_HANDLE schSCManager;
schSCManager = OpenSCManager(
NULL,
// local computer
NULL,
// ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "OpenSCManager failed (%d)", GetLastError());
return NULL;
}
return schSCManager;
}
Step 2: Create windows service to the target platform
SC_HANDLE SvcInstall(SC_HANDLE schSCManager, LPCWSTR szPath, LPCWSTR serviceName, LPCWSTR lpszServiceDisplayName)
{
SC_HANDLE schService1;
if (NULL == schSCManager)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "OpenSCManager failed (%d)", GetLastError());
return NULL;
}
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Service Name [%s]", serviceName);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Service display Name [%s]", lpszServiceDisplayName);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "path to service's binary [%s]", szPath);
schService1 = CreateServiceW(
schSCManager, // SCM database
serviceName, // name of service
lpszServiceDisplayName, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
SVC_PATH, // path to service's binary
NULL,
// no load ordering group
NULL,
// no tag identifier
NULL,
// no dependencies
NULL,
// LocalSystem account
NULL);
// no password
if (schService1 == NULL)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "CreateService failed (%d)", GetLastError());
return schService1;
}
else SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Service installed
successfully");
CloseServiceHandle(schService1);
return schService1;
}
Step 3: Fetch the service from SCM Database and start
service
int DoStartSvc(SC_HANDLE schSCManager, LPCWSTR serviceName, DWORD ServiceRights)
{
SERVICE_STATUS_PROCESS ssStatus;
DWORD dwOldCheckPoint;
DWORD dwStartTickCount;
DWORD dwWaitTime;
DWORD dwBytesNeeded;
SC_HANDLE schService;
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Service Name [%s]", serviceName);
schService = OpenServiceW(
schSCManager, // SCM database
SVC_NAME, // name of service
SERVICE_ALL_ACCESS); // need delete access
if (schService == NULL)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "DoStartSvc :OpenService failed (%d)", GetLastError());
return GetLastError();
}
// Check
the status in case the service is not stopped.
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, //
information level
(LPBYTE)&ssStatus,
// address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded)) //
size needed if buffer is too small
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "QueryServiceStatusEx failed (%d)", GetLastError());
return GetLastError();
}
// Check
if the service is already running. It would be possible
// to
stop the service here, but for simplicity this example just returns.
if (ssStatus.dwCurrentState != SERVICE_STOPPED
&& ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Cannot start the service because it is already running");
return GetLastError();
}
// Save
the tick count and initial checkpoint.
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
// Wait
for the service to stop before attempting to start it.
while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
//
Do not wait longer than the wait hint. A good interval is
//
one-tenth of the wait hint but not less than 1 second
//
and not more than 10 seconds.
dwWaitTime = ssStatus.dwWaitHint /
10;
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Current Service State Is SERVICE_STOP_PENDING");
if (dwWaitTime < 1000)
dwWaitTime = 1000;
else if (dwWaitTime > 10000)
dwWaitTime = 10000;
Sleep(dwWaitTime);
//
Check the status until the service is no longer stop pending.
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, //
information level
(LPBYTE)&ssStatus, //
address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded)) //
size needed if buffer is too small
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "QueryServiceStatusEx failed (%d)", GetLastError());
return GetLastError();
}
if (ssStatus.dwCheckPoint > dwOldCheckPoint)
{
// Continue to wait and check.
dwStartTickCount =
GetTickCount();
dwOldCheckPoint =
ssStatus.dwCheckPoint;
}
else
{
if (GetTickCount() -
dwStartTickCount > ssStatus.dwWaitHint)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Timeout waiting for service to stop");
return GetLastError();
}
}
}
//
Attempt to start the service.
if (!StartService(
schService, //
handle to service
0, //
number of arguments
NULL)) // no arguments
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "StartService failed (%d)", GetLastError());
return GetLastError();
}
else SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Service start
pending...");
// Check
the status until the service is no longer start pending.
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, // info
level
(LPBYTE)&ssStatus,
// address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded)) //
if buffer too small
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "QueryServiceStatusEx failed (%d)", GetLastError());
return GetLastError();
}
// Save
the tick count and initial checkpoint.
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
{
//
Do not wait longer than the wait hint. A good interval is
//
one-tenth the wait hint, but no less than 1 second and no
//
more than 10 seconds.
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Current Service State Is SERVICE_START_PENDING");
dwWaitTime = ssStatus.dwWaitHint /
10;
if (dwWaitTime < 1000)
dwWaitTime = 1000;
else if (dwWaitTime > 10000)
dwWaitTime = 10000;
Sleep(dwWaitTime);
//
Check the status again.
if (!QueryServiceStatusEx(
schService, //
handle to service
SC_STATUS_PROCESS_INFO, // info level
(LPBYTE)&ssStatus, //
address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded)) //
if buffer too small
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "QueryServiceStatusEx failed (%d)", GetLastError());
break;
}
if (ssStatus.dwCheckPoint > dwOldCheckPoint)
{
// Continue to wait and check.
dwStartTickCount =
GetTickCount();
dwOldCheckPoint =
ssStatus.dwCheckPoint;
}
else
{
if (GetTickCount() -
dwStartTickCount > ssStatus.dwWaitHint)
{
// No progress made within the wait hint.
break;
}
}
}
// Determine
whether the service is running.
if (ssStatus.dwCurrentState == SERVICE_RUNNING)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Service started successfully.");
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "+++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
else
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Service not started. ");
SvcLog(SVC_LOG_DEBUG, SVC_LOG, " Current
State: %d", ssStatus.dwCurrentState);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, " Exit Code:
%d", ssStatus.dwWin32ExitCode);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, " Check Point:
%d", ssStatus.dwCheckPoint);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, " Wait Hint:
%d", ssStatus.dwWaitHint);
}
CloseServiceHandle(schService);
//CloseServiceHandle(schSCManager);
return 0;
}
Step 4: Start method
will be call StartServiceCtrl_Dispatcher and Connects the main thread of
a service process to the service control manager, which causes the thread to be
the service control dispatcher thread for the calling process.
int StartServiceCtrl_Dispatcher(SERVICE_TABLE_ENTRYW* DispatchTable1)//, LPHANDLER_FUNCTION SvcCtrlHandler)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "No param will continue running service");
if (!StartServiceCtrlDispatcherW(DispatchTable1))
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, TEXT("StartServiceCtrlDispatcher"));
return 1;
}
return 0;
}
bool RegisterService_CtrlHandlerW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION SvcCtrl_Handler)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Calling C++ Wrapper Class
RegisterServiceCtrlHandlerW methods");
gSvcStatusHandle =
RegisterServiceCtrlHandlerW(
SVC_NAME,
SvcCtrlHandler);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Service Name [%s]", lpServiceName);
if (!gSvcStatusHandle)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "RegisterServiceCtrlHandler");
return false;
}
// These
SERVICE_STATUS members remain as set here
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
//
Report initial status to the SCM
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "SERVICE_START_PENDING");
return true;
}
Step 5: Set the service status like stopped, running
bool SetSvcStatus()//
SERVICE_STATUS_HANDLE hServiceStatus, SERVICE_STATUS status)
{
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Calling SvcInitService");
ghSvcStopEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual reset event
FALSE, // not signaled
NULL); // no name
if (ghSvcStopEvent == NULL)
{
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "SERVICE_STOPPED");
return false;
}
//
Report running status when initialization is complete.
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
HANDLE waitEvents[1] = {
ghSvcStopEvent
};
while (1)
{
DWORD eventRxIndex = WSAWaitForMultipleEvents(1, waitEvents, FALSE, INFINITE, FALSE);
if ((0 + WAIT_OBJECT_0) == eventRxIndex){
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Get 0 Event for controlling service");
/*Accept event received*/
//SvcCtrlHandler(eventRxIndex);
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "SERVICE_STOPPED");
}
return true;
}
SvcLog(SVC_LOG_DEBUG, SVC_LOG, "Successfully SvcInitService");
return true;
}
Service implementation in c# application
Step1: Create
console application and add ServiceInstaller helper class and implement the following functionality for communicate
Service wrapper class
using System;
using
System.Runtime.InteropServices;
namespace TeleClient
{
/// <summary>
///
/// </summary>
[Flags]
public enum ServiceRights
{
/// <summary>
///
/// </summary>
QueryConfig = 0x1,
/// <summary>
///
/// </summary>
ChangeConfig = 0x2,
/// <summary>
///
/// </summary>
QueryStatus = 0x4,
/// <summary>
///
/// </summary>
EnumerateDependants = 0x8,
/// <summary>
///
/// </summary>
Start = 0x10,
/// <summary>
///
/// </summary>
Stop = 0x20,
/// <summary>
///
/// </summary>
PauseContinue = 0x40,
/// <summary>
///
/// </summary>
Interrogate = 0x80,
/// <summary>
///
/// </summary>
UserDefinedControl = 0x100,
/// <summary>
///
/// </summary>
Delete = 0x00010000,
/// <summary>
///
/// </summary>
StandardRightsRequired = 0xF0000,
/// <summary>
///
/// </summary>
AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig |
QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
Interrogate | UserDefinedControl)
}
/// <summary>
///
/// </summary>
public enum ServiceBootFlag
{
/// <summary>
///
/// </summary>
Start = 0x00000000,
/// <summary>
///
/// </summary>
SystemStart = 0x00000001,
/// <summary>
///
/// </summary>
AutoStart = 0x00000002,
/// <summary>
///
/// </summary>
DemandStart = 0x00000003,
/// <summary>
///
/// </summary>
Disabled = 0x00000004
}
/// <summary>
///
/// </summary>
public enum ServiceState
{
/// <summary>
///
/// </summary>
Unknown = -1, // The state cannot be (has not been) retrieved.
/// <summary>
///
/// </summary>
NotFound = 0, // The service is not known on the host server.
/// <summary>
///
/// </summary>
Stop = 1, // The service is NET stopped.
/// <summary>
///
/// </summary>
Run = 2, // The service is NET started.
/// <summary>
///
/// </summary>
Stopping = 3,
/// <summary>
///
/// </summary>
Starting = 4,
}
/// <summary>
///
/// </summary>
public enum ServiceControl
{
/// <summary>
///
/// </summary>
Stop = 0x00000001,
/// <summary>
///
/// </summary>
Pause = 0x00000002,
/// <summary>
///
/// </summary>
Continue = 0x00000003,
/// <summary>
///
/// </summary>
Interrogate = 0x00000004,
/// <summary>
///
/// </summary>
Shutdown = 0x00000005,
/// <summary>
///
/// </summary>
ParamChange = 0x00000006,
/// <summary>
///
/// </summary>
NetBindAdd = 0x00000007,
/// <summary>
///
/// </summary>
NetBindRemove = 0x00000008,
/// <summary>
///
/// </summary>
NetBindEnable = 0x00000009,
/// <summary>
///
/// </summary>
NetBindDisable = 0x0000000A
}
/// <summary>
///
/// </summary>
public enum ServiceError
{
/// <summary>
///
/// </summary>
Ignore = 0x00000000,
/// <summary>
///
/// </summary>
Normal = 0x00000001,
/// <summary>
///
/// </summary>
Severe = 0x00000002,
/// <summary>
///
/// </summary>
Critical = 0x00000003
}
/// <summary>
/// Installs and provides functionality for handling windows
services
/// </summary>
public class ServiceInstaller
{
[StructLayout(LayoutKind.Sequential)]
private class SERVICE_STATUS
{
public int dwServiceType = 0;
public ServiceState dwCurrentState = 0;
public int dwControlsAccepted
= 0;
public int dwWin32ExitCode =
0;
public int
dwServiceSpecificExitCode = 0;
public int dwCheckPoint = 0;
public int dwWaitHint = 0;
}
[DllImport(@"ServiceWrapper.dll", EntryPoint = "OpenServiceControlManager")]
private static extern IntPtr OpenSCManager();
[DllImport("ServiceWrapper.dll", EntryPoint = "OpenWindowsService", CharSet = CharSet.Ansi)]
private static extern IntPtr OpenService(IntPtr hSCManager,[MarshalAs(UnmanagedType.LPStr)] string lpServiceName, ServiceRights dwDesiredAccess);
[DllImport("ServiceWrapper.dll", EntryPoint = "SvcInstall")]
private static extern IntPtr CreateService(IntPtr hSCManager, string
lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int
dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl,
string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string
lpDependencies, string lp, string lpPassword);
[DllImport("ServiceWrapper.dll", EntryPoint = "SvcInstall")]
private static extern IntPtr CreateService(IntPtr hSCManager, [MarshalAs(UnmanagedType.LPStr)] string
szPath, [MarshalAs(UnmanagedType.LPStr)] string lpServiceName, [MarshalAs(UnmanagedType.LPStr)] string lpDisplayName);
[DllImport("ServiceWrapper.dll", EntryPoint = "CloseServiceHandler")]
private static extern int CloseServiceHandle(IntPtr hSCObject);
[DllImport("ServiceWrapper.dll", EntryPoint = "QueryServiceStatus")]
private static extern int QueryServiceStatus(IntPtr hService,
SERVICE_STATUS lpServiceStatus);
[DllImport("ServiceWrapper.dll", SetLastError = true)]
private static extern int DeleteService(IntPtr schSCManager,[MarshalAs(UnmanagedType.LPStr)] string serviceName);
[DllImport("ServiceWrapper.dll")]
private static extern int ControlService(IntPtr hService, ServiceControl
dwControl, SERVICE_STATUS lpServiceStatus);
[DllImport("ServiceWrapper.dll", EntryPoint = "DoStartSvc")]
private static extern int StartService(IntPtr hSCManager, [MarshalAs(UnmanagedType.LPStr)] string
lpServiceName);
[DllImport("ServiceWrapper.dll", EntryPoint = "ReportServiceStatus")]
private static extern int ReportServiceStatus([MarshalAs(UnmanagedType.LPStr)] string ServiceName);
/// <summary>
///
/// </summary>
public ServiceInstaller()
{
}
/// <summary>
/// Takes a service name and tries to stop and then uninstall
the windows serviceError
/// </summary>
/// <param name="ServiceName">The windows service
name to uninstall</param>
public static void Uninstall(string ServiceName)
{
IntPtr scman =
OpenServiceControlManager();
try
{
IntPtr service =
OpenService(scman, ServiceName, ServiceRights.StandardRightsRequired | ServiceRights.Stop |
ServiceRights.QueryStatus);
if (service == IntPtr.Zero)
{
throw new ApplicationException("Service not
installed.");
}
try
{
StopService(service);
int ret =
DeleteService(service, ServiceName);
if (ret == 0)
{
int error = Marshal.GetLastWin32Error();
throw new ApplicationException("Could not
delete service " + error);
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
finally
{
CloseServiceHandle(service);
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
finally
{
CloseServiceHandle(scman);
}
}
/// <summary>
/// Accepts a service name and returns true if the service
with that service name exists
/// </summary>
/// <param name="ServiceName">The service name
that we will check for existence</param>
/// <returns>True if that service exists false
otherwise</returns>
public static bool ServiceIsInstalled(string ServiceName)
{
IntPtr scman =
OpenServiceControlManager();
try
{
IntPtr service =
OpenService(scman, ServiceName, ServiceRights.QueryStatus);
if (service == IntPtr.Zero) return false;
CloseServiceHandle(service);
return true;
}
finally
{
CloseServiceHandle(scman);
}
}
/// <summary>
/// Takes a service name, a service display name and the path
to the service executable and installs / starts the windows service.
/// </summary>
/// <param name="ServiceName">The service name
that this service will have</param>
/// <param name="DisplayName">The display name
that this service will have</param>
/// <param name="FileName">The path to the
executable of the service</param>
public static void Install(string ServiceName, string DisplayName, string FileName)
{
Logger.Log.Info("Try to open SC
Manager");
IntPtr scman =
OpenServiceControlManager();
try
{
Logger.Log.Info("Create
Tele service ");
IntPtr service = CreateService(scman,
FileName, ServiceName, DisplayName);
if (service == IntPtr.Zero)
{
throw new ApplicationException("Failed to
install service.");
}
}
catch
{
throw;
}
finally
{
CloseServiceHandle(scman);
}
}
/// <summary>
/// Takes a service name and starts it
/// </summary>
/// <param name="serviceName">The service name</param>
public static void StartService(string serviceName)
{
IntPtr scman =
OpenServiceControlManager();
try
{
IntPtr hService =
OpenService(scman, serviceName, ServiceRights.QueryStatus |
ServiceRights.Start);
Logger.Log.Info("Successfully
opened SCManager");
if (hService == IntPtr.Zero)
{
throw new ApplicationException("Could not
open service.");
}
try
{
StartService(hService,
serviceName);
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
finally
{
CloseServiceHandle(hService);
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
finally
{
CloseServiceHandle(scman);
}
}
/// <summary>
/// Stops the provided windows service
/// </summary>
/// <param name="Name">The service name
that will be stopped</param>
public static void StopService(string Name)
{
IntPtr scman =
OpenServiceControlManager();
try
{
IntPtr hService =
OpenService(scman, Name, ServiceRights.QueryStatus | ServiceRights.Stop);
Console.Write("Successfullt
opened SCManager");
if (hService == IntPtr.Zero)
{
throw new ApplicationException("Could not
open service.");
}
try
{
StopService(hService);
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
finally
{
CloseServiceHandle(hService);
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
finally
{
CloseServiceHandle(scman);
}
}
/// <summary>
/// Stars the provided windows service
/// </summary>
/// <param name="hService">The handle to the
windows service</param>
private static void StartService(IntPtr hService, string serviceName, int? state = null)
{
SERVICE_STATUS status = new SERVICE_STATUS();
StartService(hService,
serviceName);
Console.Write("~: Service
started Successfully");
WaitForServiceStatus(hService,
ServiceState.Starting, ServiceState.Run);
}
/// <summary>
/// Stops the provided windows service
/// </summary>
/// <param name="hService">The handle to the
windows service</param>
public static void ReportSvcStatus(string ServiceName)
{
ReportServiceStatus(ServiceName);
Logger.Log.Info("Service
successfully started");
}
/// <summary>
/// Stops the provided windows service
/// </summary>
/// <param name="hService">The handle to the
windows service</param>
private static void StopService(IntPtr hService)
{
SERVICE_STATUS status = new SERVICE_STATUS();
ControlService(hService, ServiceControl.Stop, status);
Console.Write("Service
stoped Successfully");
WaitForServiceStatus(hService, ServiceState.Stopping, ServiceState.Stop);
}
/// <summary>
/// Takes a service name and returns the <code>ServiceState</code> of the
corresponding service
/// </summary>
/// <param name="ServiceName">The service name
that we will check for his <code>ServiceState</code></param>
/// <returns>The ServiceState of the service we wanted
to check</returns>
public static ServiceState GetServiceStatus(string ServiceName)
{
IntPtr scman =
OpenServiceControlManager();
try
{
IntPtr hService =
OpenService(scman, ServiceName,
ServiceRights.QueryStatus);
if (hService == IntPtr.Zero)
{
return ServiceState.NotFound;
}
try
{
return
GetServiceStatus(hService);
}
finally
{
CloseServiceHandle(scman);
}
}
finally
{
CloseServiceHandle(scman);
}
}
/// <summary>
/// Gets the service state by using the handle of the
provided windows service
/// </summary>
/// <param name="hService">The handle to the
service</param>
/// <returns>The <code>ServiceState</code> of the service</returns>
private static ServiceState GetServiceStatus(IntPtr hService)
{
SERVICE_STATUS ssStatus = new SERVICE_STATUS();
Logger.Log.Info("make query
for service status.");
if
(QueryServiceStatus(hService, ssStatus) == 0)
{
Logger.Log.Info("Failed to
query service status.");
throw new ApplicationException("Failed to
query service status.");
}
return
ssStatus.dwCurrentState;
}
/// <summary>
/// Returns true when the service status has been changes
from wait status to desired status
/// ,this method waits around 10 seconds for this operation.
/// </summary>
/// <param name="hService">The handle to the
service</param>
/// <param name="WaitStatus">The current state of
the service</param>
/// <param name="DesiredStatus">The desired state of
the service</param>
/// <returns>bool if the service has successfully
changed states within the allowed timeline</returns>
private static bool WaitForServiceStatus(IntPtr hService, ServiceState
WaitStatus, ServiceState DesiredStatus)
{
SERVICE_STATUS ssStatus = new SERVICE_STATUS();
int dwOldCheckPoint;
int dwStartTickCount;
Logger.Log.Info("make query
for service status and WaitForServiceStatus.");
QueryServiceStatus(hService,
ssStatus);
if (ssStatus.dwCurrentState
== DesiredStatus) return true;
dwStartTickCount = Environment.TickCount;
dwOldCheckPoint =
ssStatus.dwCheckPoint;
while
(ssStatus.dwCurrentState == WaitStatus)
{
// Do not wait
longer than the wait hint. A good interval is
// one tenth the
wait hint, but no less than 1 second and no
// more than 10
seconds.
int dwWaitTime =
ssStatus.dwWaitHint / 10;
if (dwWaitTime <
1000) dwWaitTime = 1000;
else if (dwWaitTime >
10000) dwWaitTime = 10000;
System.Threading.Thread.Sleep(dwWaitTime);
// Check the status
again.
Logger.Log.Info("QueryServiceStatus(hService,
ssStatus) == 0");
if
(QueryServiceStatus(hService, ssStatus) == 0) break;
if
(ssStatus.dwCheckPoint > dwOldCheckPoint)
{
// The service is
making progress.
dwStartTickCount = Environment.TickCount;
dwOldCheckPoint =
ssStatus.dwCheckPoint;
}
else
{
if (Environment.TickCount -
dwStartTickCount > ssStatus.dwWaitHint)
{
// No progress made
within the wait hint
break;
}
}
}
return
(ssStatus.dwCurrentState == DesiredStatus);
}
/// <summary>
/// Opens the service manager
/// </summary>
/// <param name="Rights">The service manager
rights</param>
/// <returns>the handle to the service manager</returns>
private static IntPtr OpenServiceControlManager()
{
IntPtr scman =
OpenSCManager();
if (scman == IntPtr.Zero)
{
Console.Write("Could not
connect to service control manager.");
throw new ApplicationException("Could not
connect to service control manager.");
}
return scman;
}
}
}
Step 2: Implement install,start,stop and uninstall functionality in program main method
using System;
using System.IO;
using
System.Threading.Tasks;
using
TeleClient.General;
using System.Threading;
using Windows.Networking.Connectivity;
using System.Linq;
using System.Xml.Linq;
using System.Xml;
using
Windows.Networking.Sockets;
using Windows.Networking;
using
System.Runtime.InteropServices;
using
System.Security.Principal;
using
Windows.Networking.NetworkOperators;
using Windows.Storage;
using
Windows.Networking.BackgroundTransfer;
using
System.Security.Permissions;
using
Windows.Devices.Geolocation;
using
System.Security.AccessControl;
using
TeleClient.General.Enum;
using TelemtryClient;
using Microsoft.Win32;
using System.Text;
namespace TeleClient
{
class Program
{
static string serviceName = "TeleClient";
static AutoResetEvent evnt = new AutoResetEvent(false);
[MTAThread]
static void Main(string[] args)
{
try
{
Logger.Log.Info("Application
starting...");
if (args.Length >
0)
{
if (args[0] == "install")
{
Logger.Log.Info("Install
service.... ");
//Installs and
starts the service
ServiceInstaller.Install(serviceName,
"TeleClient", @"C:\\test\\ServiceTools\\TeleClient.exe");
Logger.Log.Info("try to start
service service");
StartService(args,
serviceName);
}
else if (args[0] == "start")
{
Logger.Log.Info("Start
service");
StartService(args,
serviceName);
}
else if (args[0] == "stop")
{
Logger.Log.Info("Start
service");
ServiceInstaller.StopService(serviceName);
}
else if (args[0] == "uninstall")
{
Logger.Log.Info("Start
service");
ServiceInstaller.StopService(serviceName);
ServiceInstaller.Uninstall(serviceName);
}
}
else
{
Logger.Log.Info("Calling
service class by API");
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new ClientService()
};
ServiceBase.Run(ServicesToRun);
}
Logger.Log.Info("~:
Initialized service1 constructor");
}
catch (Exception ex)
{
Logger.Log.Info("Error On
main : " + ex.Message);
Logger.Log.Info(ex.StackTrace);
if (ex.InnerException
!= null)
{
Logger.Log.Info("Inner
Exception");
Logger.Log.Info(ex.InnerException.Message);
Logger.Log.Info(ex.InnerException.StackTrace);
}
}
}
static void StartService(string[] args, string serviceName)
{
Logger.Log.Info("~: Service
is installed. Attempting to start
service.");
ServiceController sc = new ServiceController();
sc.ServiceName = serviceName;
Logger.Log.Info("~: Check
service Status. Attempting to start
service.");
Logger.Log.Info(string.Format("Starting
{0}: ", sc.ServiceName));
try
{
sc.Start(args);
sc.WaitForStatus(ServiceControllerStatus.Running);
Logger.Log.Info("~: Service
started sccuessfully");
}
catch (Exception ex)
{
Logger.Log.Info(ex.Message);
}
}
}
public partial class ClientService : ServiceBase
{
public ClientService ()
{
Logger.Log.Info("~: Client
Constructor Initialized ");
this.ServiceName = "MyServiceName";
this.CanShutdown = true;
this.CanStop = true;
}
protected override void OnStart(string[] args)
{
InitializeEventUploadTimer()
Logger.Log.Info("~: Completed
InitializeDirectory");
base.OnStart(args);
}
#region InitializeComponent
private void InitializeDirectory()
{
Logger.Log.Info("~:
#######################################################################");
Logger.Log.Info("~: ######");
Logger.Log.Info("~:
###### STARTING: " + System.DateTime.Now.ToLongTimeString());
Logger.Log.Info("~:
######");
Logger.Log.Info("~:
#######################################################################" + System.Environment.NewLine);
}
private void InitializeEventUploadTimer()
{
Logger.Log.Info("~:
Initializing EventUploadTimer");
int Interval;
int.TryParse(Utility.GetAppSettings(FilePaths.ConfigFilePath, "EventElapsedTiming"), out Interval);
Interval = Interval * 60 * 1000;
bool set = true;
Task.Factory.StartNew(async () =>
{
while (set)
{
Logger.Log.Info(string.Format("Task delay : {0}", DateTime.Now.ToString()));
await Task.Delay(Interval);
Logger.Log.Info(string.Format("Timer
Elapsed : {0}", DateTime.Now.ToString()));
}
});
Logger.Log.Info(string.Format("process
completed : {0}", DateTime.Now.ToString()));
}
#endregion
protected override void OnStop()
{
ServiceInstaller.StopService(ServiceName);
}
}
}
1.Installing and running Service
on Windows Threshold Mobile
i.
Copy files from your desktop to device
putd <Source File Path on Dev
Machine> <Destination path on Threshold Mobile Machine>
e.g. putd C:\TestSolution\Release\WindowsService.exe C:\test\
ii.
Install windows service in your Threshold Mobile
device.
cmd-device <path to service
exe> '"install"'
e.g. cmd-device C:\test\WindowsService.exe '"install"'
The exe must follow appropriate
code flow for handling “install” parameter
iii.
Uninstall windows service in your Threshold
Mobile device.
cmd-device <path to service
exe> '"uninstall"'
e.g. cmd-device C:\test\WindowsService.exe '"uninstall"'
The exe must follow appropriate
code flow for handling “uninstall” parameter
iv.
Start the windows service in your Threshold
Mobile device.
cmd-device <path to service
exe> '"start"'
e.g. cmd-device C:\test\WindowsService.exe '"start"'
The exe must follow appropriate
code flow for handling “start” parameter
v.
To list available window service using this
command:
cmd-device net start
vi.
To get service status use this command
cmd-device sc query [ServiceName]
vii.
To start the service use this command:
cmd-device sc start [ServiceName]
viii.
To stop the service use this command:
cmd-device sc stop [ServiceName]
ix.
To delete the service use this command:
cmd-device sc delete
[ServiceName]
2.
List of APIs available with mincore.lib
a.
The list of API’s supported by mincore.lib is
available in document “MincoreLibApis.txt”
available here.
b.
Alternatively you can get this by running
following command on Visual Studio Developer Command Line Prompt.
dumpbin /exports c:\Program Files
(x86)\Windows Kits\8.2\Lib\winv6.4\um\x86\mincore.lib
No comments:
Post a Comment