xentara-utils v2.1
The Xentara Utility Library
Loading...
Searching...
No Matches
xentara::utils::windows::service Namespace Reference

Windows service functionality. More...

Namespaces

namespace  placeholderTypes
 Namespace containing dummy types for use on non-Windows platforms.
 

Classes

class  LogStream
 Streams that logs messages for a Windows service. More...
 
class  ServiceDefinition
 A definition of a Windows Service. More...
 
class  ServiceHandle
 A Windows service handle that closes itself on destruct. More...
 
struct  ServiceOptions
 Options for a Windows service. More...
 

Functions

auto log (const EVENT_DESCRIPTOR &event, std::string_view message) -> void
 Logs a message for a Windows service.
 
template<typename... Arguments>
auto format (const EVENT_DESCRIPTOR &event, std::string_view format, Arguments &&...arguments) -> void
 Formats a message and logs it for a Windows service.
 
auto vformat (const EVENT_DESCRIPTOR &event, std::string_view format, std::format_args arguments) -> void
 Formats a message and logs it for a Windows service.
 
auto logFatalError (const std::exception &exception) -> void
 Logs a fatal exception for a Windows service.
 
auto isLoggingEnabled () noexcept -> bool
 Checks whether the logging functions will actually log anything.
 
auto isService () noexcept -> bool
 Checks whether the current process is running as a Windows service.
 
auto isSystemService () -> bool
 Checks whether the current process is running as a Windows service under one of the built-in Windows Service User Accounts.
 
auto isSystemServiceAccount (PSID sid) noexcept -> bool
 Checks whether an SID is one of the built-in Windows Service User Accounts.
 
template<tparam::String kServiceName, ServiceMainFunction kServiceMain, const GUID & kEventProvider, const EVENT_DESCRIPTOR & kFatalErrorEvent, ServiceOptions kOptions>
auto run (const ServiceDefinition< kServiceName, kServiceMain, kEventProvider, kFatalErrorEvent, kOptions > &serviceDefinition, int argc, char *argv[]) -> int
 Runs a main() function either directly or as a Windows service, as appropriate.
 
template<tparam::String kServiceName, ServiceMainFunction kServiceMain, const GUID & kEventProvider, const EVENT_DESCRIPTOR & kFatalErrorEvent, ServiceOptions kOptions>
auto tryRunAsWindowsService (const ServiceDefinition< kServiceName, kServiceMain, kEventProvider, kFatalErrorEvent, kOptions > &serviceDefinition) -> std::optional< int >
 Checks if the current process is being run as a Windows service and runs the service control loop if it is.
 

Detailed Description

Windows service functionality.

This namespace contains functionality related to Windows services.

Function Documentation

◆ format()

template<typename... Arguments>
auto xentara::utils::windows::service::format ( const EVENT_DESCRIPTOR &  event,
std::string_view  format,
Arguments &&...  arguments 
) -> void

Formats a message and logs it for a Windows service.

This function checks whether the current process is running as a Windows service, and writes a formatted message to the event log if it is. This is more efficient than formatting the message beforehand and then logging it, as formatting is skipped if logging is disabled.

Note
On non-Windows platforms, this function is a noop.
Include file
#include <xentara/utils/windows/service/log.hpp>
Parameters
eventThe event that should be used to log the message. This event must belong to the provider identified by the kEventProvider of the service definition that was used to start the service, and it must have a single user data of type win:UnicodeString, that will be set to the message.
formatThe format string.
argumentsThe arguments for the format.

◆ isLoggingEnabled()

auto xentara::utils::windows::service::isLoggingEnabled ( ) -> bool
noexcept

Checks whether the logging functions will actually log anything.

You can use this function to skip expensive preparation for loggin if logging is disabled because the current process is not running as a Windows service.

Include file
#include <xentara/utils/windows/service/log.hpp>
Returns
Return true if the logging function will actually log something, or false if they are noops.

◆ isService()

auto xentara::utils::windows::service::isService ( ) -> bool
noexcept

Checks whether the current process is running as a Windows service.

Include file
#include <xentara/utils/windows/service/service.hpp>
Returns
Return true if the current process is running as a Windows service, or false if if is running as a regular application./// Under non-Windows platforms, this function always returns false.

◆ isSystemService()

auto xentara::utils::windows::service::isSystemService ( ) -> bool

Checks whether the current process is running as a Windows service under one of the built-in Windows Service User Accounts.

This function allows you to check whether the current process is running as a Windows service under one of the Windows Service User Accounts. This can be used to use different access permissions for services and normal applications.

Normally, debug and diagnostics access should be restricted to the user running the application. If the application is running as a service under one of the built-in Service User Accounts, however, this is not very useful, because diagnositcs tools cannot be run under a service account. In that case, all users should have diagnosics access. You can use the return value of this function to select the correct permissions.

This function checks the effective thread ID of the current thread to determine the user account. If the current thread was assigned an impersonation token, then the impersonated user will be used for the check.

Include file
#include <xentara/utils/windows/service/service.hpp>
Returns
Returns true if the current process is not running as a Windows service under the LocalService, NetworkService, or [LocalSystem ](https://learn.microsoft.com/en-us/windows/win32/services/localsystem-account Account. If the current process is not running as a Windows service, or if the service is running under a regular user Account, this function returns false. Under non-Windows platforms, this function always returns false.
Note
If you want to open a named pipe server, you can use the scope Scope::Service to automatically assign the correct permissions, rather than relying on this function.
Exceptions
std::runbtime_errorAn error occurred getting the owner of the current thread.
See also
ipc::NamedPipeServer::Scope::Service.

◆ isSystemServiceAccount()

auto xentara::utils::windows::service::isSystemServiceAccount ( PSID  sid) -> bool
noexcept

Checks whether an SID is one of the built-in Windows Service User Accounts.

Note
This function is only available under Windows.
Include file
#include <xentara/utils/windows/service/service.hpp>
Parameters
sidThe SID to check
Returns
Returns true if sid is the SID of the LocalService Account, NetworkService Account, or the [LocalSystem ](https://learn.microsoft.com/en-us/windows/win32/services/localsystem-account Account.

◆ log()

auto xentara::utils::windows::service::log ( const EVENT_DESCRIPTOR &  event,
std::string_view  message 
) -> void

Logs a message for a Windows service.

This function checks whether the current process is running as a Windows service, and writes a message to the event log if it is.

Note
On non-Windows platforms, this function is a noop.
Include file
#include <xentara/utils/windows/service/log.hpp>
Parameters
eventThe event that should be used to log the message. This event must belong to the provider identified by the kEventProvider of the service definition that was used to start the service, and it must have a single user data of type win:UnicodeString, that will be set to the message.
messageThe message to log.

◆ logFatalError()

auto xentara::utils::windows::service::logFatalError ( const std::exception &  exception) -> void

Logs a fatal exception for a Windows service.

This function checks whether the current process is running as a Windows service, and writes a fatal error to the event log if it is. The caller should exit the application with exit code EXIT_FAILURE after calling this function.

Note
On non-Windows platforms, this function is a noop.
Include file
#include <xentara/utils/windows/service/log.hpp>
Parameters
exceptionThe exception that caused the error.

◆ run()

template<tparam::String kServiceName, ServiceMainFunction kServiceMain, const GUID & kEventProvider, const EVENT_DESCRIPTOR & kFatalErrorEvent, ServiceOptions kOptions>
auto xentara::utils::windows::service::run ( const ServiceDefinition< kServiceName, kServiceMain, kEventProvider, kFatalErrorEvent, kOptions > &  serviceDefinition,
int  argc,
char *  argv[] 
) -> int

Runs a main() function either directly or as a Windows service, as appropriate.

This function checks whether the current process is being run as a Windows service, and starts the Windows service control loop if it is. Once the service has exited, the function will return the exit code that the caller should return from the global main() function.

If the calling process is not a Windows service started by the Windows Service manager, this function will execute the service main function defined in serviceDefinition directly, passing it the parameters argc and argv, and returning the result. This allows you to execute a main()-like function directly or as a service, as appropriate.

An application that can optionally run as a Windows service might look something like this:

#include <xentara/utils/windows/service/ServiceDefinition.hpp>
#include <cstdlib>
#ifdef _WIN32
// This should be the header file generated by the Microsoft Message Compiler (mc.exe) from the ETW manifest file
# include <MyGeneratedEventLoggingHeader.h>
#else // _WIN32
// These are dummy declarations to be used on non-Windows platforms
constexpr GUID ServiceEventProviderGuid {};
constexpr EVENT_DESCRIPTOR ServiceFatalErrorEvent {};
#endif // _WIN32
namespace myApplication
{
auto main(int argc, char *argv[]) -> int
{
// TODO: put the code that would otherwise be in the global main() function here
return EXIT_SUCCESS;
}
}
auto main(int argc, char *argv[]) -> int
{
"MyService",
&myApplication::main,
ServiceEventProviderGuid,
ServiceFatalErrorEvent> kServiceDefinition;
return run(kServiceDefinition, argc, argv);
}
A definition of a Windows Service.
Definition ServiceDefinition.hpp:271
Namespace containing dummy types for use on non-Windows platforms.
Definition ServiceDefinition.hpp:91
__opaque_literal_type__ EVENT_DESCRIPTOR
A dummy type that can be used as kFatalErrorEvent template parameter for ServiceDefinition on non-Win...
Definition ServiceDefinition.hpp:129
__opaque_literal_type__ GUID
A dummy type that can be used as kEventProvider template parameter for ServiceDefinition on non-Windo...
Definition ServiceDefinition.hpp:111
auto run(const ServiceDefinition< kServiceName, kServiceMain, kEventProvider, kFatalErrorEvent, kOptions > &serviceDefinition, int argc, char *argv[]) -> int
Runs a main() function either directly or as a Windows service, as appropriate.
Definition ServiceDefinition.hpp:368
Note
On non-Windows platforms, this function is always calls the service main function directly.
Parameters
serviceDefinitionThe definition of the service
argcThe parameter count to pass to the service main function if the process is not a Windows service.
argvThe parameter array to pass to the service main function if the process is not a Windows service.
Returns
Returns the exit code the caller should return from the global main() function.

◆ tryRunAsWindowsService()

template<tparam::String kServiceName, ServiceMainFunction kServiceMain, const GUID & kEventProvider, const EVENT_DESCRIPTOR & kFatalErrorEvent, ServiceOptions kOptions>
auto xentara::utils::windows::service::tryRunAsWindowsService ( const ServiceDefinition< kServiceName, kServiceMain, kEventProvider, kFatalErrorEvent, kOptions > &  serviceDefinition) -> std::optional<int>

Checks if the current process is being run as a Windows service and runs the service control loop if it is.

This function checks whether the current process is being run as a Windows service, and starts the Windows service control loop if it is. Once the service has exited, the function will return the exit code that the caller should return from the global main() function.

If the calling process is not a Windows service started by the Windows Service manager, the function will return std::nullopt. The caller should then handle the application like a normal, non-service process.

This function is only intended for advanced scenarios, where the application behaves very differently with and without a Windows service. Generally, the easiest way to run an application as a possible Windows service is by using the simple run() function.

Note
On non-Windows platforms, this function is a noop and always returns std::nullopt.
Parameters
serviceDefinitionThe definition of the service
Returns
Returns the exit code the caller should return from the global main() function, or std::nullopt if the calling process is not being run as a service.
See also
run()

◆ vformat()

auto xentara::utils::windows::service::vformat ( const EVENT_DESCRIPTOR &  event,
std::string_view  format,
std::format_args  arguments 
) -> void

Formats a message and logs it for a Windows service.

This function checks whether the current process is running as a Windows service, and writes a formatted message to the event log if it is. This is more efficient than formatting the message beforehand and then logging it, as formatting is skipped if logging is disabled.

Note
On non-Windows platforms, this function is a noop.
Include file
#include <xentara/utils/windows/service/log.hpp>
Parameters
eventThe event that should be used to log the message. This event must belong to the provider identified by the kEventProvider of the service definition that was used to start the service, and it must have a single user data of type win:UnicodeString, that will be set to the message.
formatThe format string.
argumentsThe arguments for the format.