4#include "Stroika/Frameworks/StroikaPreComp.h"
10#include "Stroika/Foundation/Debug/Fatal.h"
13#include "Stroika/Foundation/Execution/CommandLine.h"
15#include "Stroika/Foundation/Execution/SignalHandlers.h"
17#if qStroika_Foundation_Common_Platform_Windows
18#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
19#include "Stroika/Foundation/Execution/Platform/Windows/StructuredException.h"
23#include "Stroika/Frameworks/Service/Main.h"
25#include "AppVersion.h"
54using Memory::MakeSharedPtr;
64 if (not e.As<
String> ().empty ()) {
65 cerr <<
"Error: " << e.As<
String> () << endl;
68 cerr <<
"Usage: " << m.GetServiceDescription ().fRegistrationName <<
" [options] where options can be :\n ";
70 cerr <<
"\t--" <<
String{Main::CommandNames::kInstall}
71 <<
" /* Install service (only when debugging - should use real installer like WIX) */" << endl;
72 cerr <<
"\t--" <<
String{Main::CommandNames::kUnInstall}
73 <<
" /* UnInstall service (only when debugging - should use real installer like WIX) */" << endl;
75 cerr <<
"\t--" <<
String{Main::CommandNames::kRunAsService}
76 <<
" /* Run this process as a service (doesn't exit until the service is done ...) */" << endl;
77 cerr <<
"\t--" <<
String{Main::CommandNames::kRunDirectly} <<
" /* Run this process as a directly (doesn't exit until the service is done or ARGUMENT TIMEOUT seconds elapsed ...) but not using service infrastructure */"
79 cerr <<
"\t--" <<
String{Main::CommandNames::kStart} <<
" /* Service/Control Function: Start the service */" << endl;
80 cerr <<
"\t--" <<
String{Main::CommandNames::kStop} <<
" /* Service/Control Function: Stop the service */" << endl;
81 cerr <<
"\t--" <<
String{Main::CommandNames::kForcedStop}
82 <<
" /* Service/Control Function: Forced stop the service (after trying to normally stop) */" << endl;
83 cerr <<
"\t--" <<
String{Main::CommandNames::kRestart}
84 <<
" /* Service/Control Function: Stop and then re-start the service (ok if already stopped) */" << endl;
85 cerr <<
"\t--" <<
String{Main::CommandNames::kForcedRestart}
86 <<
" /* Service/Control Function: Stop (force if needed) and then re-start the service (ok if already stopped) */" << endl;
87 cerr <<
"\t--" <<
String{Main::CommandNames::kReloadConfiguration} <<
" /* Reload service configuration */" << endl;
88 cerr <<
"\t--" <<
String{Main::CommandNames::kPause} <<
" /* Service/Control Function: Pause the service */" << endl;
89 cerr <<
"\t--" <<
String{Main::CommandNames::kContinue} <<
" /* Service/Control Function: Continue the paused service */" << endl;
90 cerr <<
"\t--Status /* Service/Control Function: Print status of running service */ " << endl;
91 cerr <<
"\t--Version /* print this application version */ " << endl;
92 cerr <<
"\t--help /* Print this help. */ " << endl;
94 <<
"\tExtra unrecognized parameters for start/restart, and forced restart operations will be passed along to the actual "
101int main (
int argc,
const char* argv[])
106#if qStroika_Foundation_Execution_Thread_SupportThreadStatistics
107 [[maybe_unused]]
auto&& cleanupReport =
108 Finally ([] () {
DbgTrace (
"Exiting main with thread {} running"_f, Thread::GetStatistics ().fRunningThreads); });
119#if qStroika_Foundation_Common_Platform_Windows
133#if qStroika_Foundation_Common_Platform_POSIX
146 .fLogBufferingEnabled =
true,
147 .fSuppressDuplicatesThreshold = 15s,
149 bool dockerContainerFlag =
false;
150 if (dockerContainerFlag) {
151 using namespace IO::FileSystem;
152 Logger::sThe.AddAppender (
153 MakeSharedPtr<Logger::StreamAppender> (FileOutputStream::New (STDOUT_FILENO, FileStream::AdoptFDPolicy::eDisconnectOnDestruction)));
156#if qStroika_HasComponent_syslog
157 Logger::sThe.SetAppenders (MakeSharedPtr<Logger::SysLogAppender> (
"Stroika-Sample-Service"sv));
158#elif qStroika_Foundation_Common_Platform_Windows
159 Logger::sThe.SetAppenders (MakeSharedPtr<Logger::WindowsEventLogAppender> (
"Stroika-Sample-Service"sv));
164#if qStroika_Foundation_Debug_TraceToFile
165 Logger::sThe.Log (Logger::eInfo,
"Debugging Log2TraceFile: {}"_f, Debug::GetTraceFileName ());
173 serviceIntegrationRep = MakeSharedPtr<Main::LoggerServiceWrapper> (serviceIntegrationRep);
179 Main m{MakeSharedPtr<Samples::Service::SampleAppServiceRep> (), serviceIntegrationRep};
185 using StandardCommandLineOptions::kHelp;
186 using StandardCommandLineOptions::kVersion;
190 cmdLine.Validate (allMyOptions);
192 if (cmdLine.Has (Main::CommandOptions::kStatus)) {
196 else if (cmdLine.Has (kHelp)) {
200 else if (cmdLine.Has (kVersion)) {
201 cout << m.GetServiceDescription ().fPrettyName <<
": "sv << Characters::ToString (AppVersion::kVersion) << endl;
215 String exceptMsg = Characters::ToString (current_exception ());
217 Logger::sThe.Log (Logger::eError,
"{}"_f, exceptMsg);
219 cerr <<
"FAILED: " << exceptMsg << endl;
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual T AsUTF8() const
A generalization of a vector: a container whose elements are keyed by the natural numbers.
nonvirtual void SetSignalHandlers(SignalID signal)
nonvirtual void SetStandardCrashHandlerSignals(SignalHandler handler=SignalHandler{DefaultCrashSignalHandler, SignalHandler::Type::eDirect}, const Containers::Set< SignalID > &forSignals=GetStandardCrashSignals())
static const SignalHandler kIGNORED
static SignalHandlerRegistry sThe
static shared_ptr< IServiceIntegrationRep > mkDefaultServiceIntegrationRep()
nonvirtual Containers::Set< ServiceIntegrationFeatures > GetServiceIntegrationFeatures() const
nonvirtual void Run(const CommandArgs &args, const Streams::OutputStream::Ptr< Characters::Character > &out=nullptr)
nonvirtual String GetServiceStatusMessage() const
void DefaultLoggingCrashSignalHandler(Execution::SignalID signal) noexcept
void DefaultLoggingFatalErrorHandler(const Characters::SDKChar *msg) noexcept
auto Finally(FUNCTION &&f) -> Private_::FinallySentry< FUNCTION >