Skip to content

Commit

Permalink
win32: Forte as a Windows service
Browse files Browse the repository at this point in the history
  • Loading branch information
kumajaya committed May 5, 2024
1 parent 1bda348 commit b5089e4
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 27 deletions.
10 changes: 10 additions & 0 deletions src/arch/utils/mainparam_utils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*******************************************************************************
* Copyright (c) 2018 fortiss GmbH
* 2024 Samator Indo Gas
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
Expand All @@ -9,6 +10,7 @@
* Contributors:
* Tarik Terzimehic
* - initial API and implementation and/or initial documentation
* Ketut Kumajaya - option to run as a Windows service
*******************************************************************************/

#include <forte_config.h>
Expand Down Expand Up @@ -40,6 +42,10 @@ void listHelp(){
#ifdef FORTE_TRACE_CTF
printf("%-20s Set the output directory for TRACE_CTF\n", " -t <directory>");
#endif //FORTE_TRACE_CTF
#ifdef FORTE_WINDOWS_SERVICE
printf("%-20s To install as a Windows service\n", " -install");
printf("%-20s To remove the service\n", " -remove");
#endif //FORTE_WINDOWS_SERVICE
}

/*!\brief Parses the command line arguments passed to the main function
Expand Down Expand Up @@ -90,6 +96,10 @@ const char *parseCommandLineArguments(int argc, char *arg[]){
barectfSetup(arg[i + 1] ?: "");
break;
#endif //FORTE_TRACE_CTF
#ifdef FORTE_WINDOWS_SERVICE
case 's':
break;
#endif //FORTE_WINDOWS_SERVICE
default: //! Unknown parameter or -h -> Lists the help for FORTE
return "";
}
Expand Down
2 changes: 2 additions & 0 deletions src/arch/win32/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#*******************************************************************************
# Copyright (c) 2010 - 2015 ACIN, Profactor GmbH, fortiss GmbH
# 2024 Samator Indo Gas
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0.
Expand All @@ -9,6 +10,7 @@
# Contributors:
# Alois Zoitl, Gerhard Ebenhofer, Martin Melik-Merkumians - initial API and implementation and/or initial documentation
# Christoph Binder - add possibility to configure simulated time
# Ketut Kumajaya - option to run as a Windows service
# *******************************************************************************/

SET(SOURCE_GROUP ${SOURCE_GROUP}\\win32)
Expand Down
10 changes: 9 additions & 1 deletion src/arch/win32/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*******************************************************************************
* Copyright (c) 2010 - 2018 ACIN, Profactor GmbH, fortiss GmbH
* 2024 Samator Indo Gas
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
Expand All @@ -9,6 +10,7 @@
* Contributors:
* Alois Zoitl, Ingo Hegny, Gerhard Ebenhofer - initial API and implementation and/or initial documentation
* Alois Zoitl - cleaned up main, inserted new architecture initilasation api
* Ketut Kumajaya - option to run as a Windows service
*******************************************************************************/
#include "../forte_architecture.h"
#include "../devlog.h"
Expand Down Expand Up @@ -61,7 +63,7 @@ void createDev(const char *paMGRID){
delete poDev;
}

int main(int argc, char *arg[]){
int _main(int argc, char *arg[]){

if(CForteArchitecture::initialize()){

Expand All @@ -83,3 +85,9 @@ int main(int argc, char *arg[]){
}
return 0;
}

#ifndef FORTE_WINDOWS_SERVICE
int main(int argc, char *arg[]){
return _main(argc, arg);
}
#endif
5 changes: 2 additions & 3 deletions src/arch/win32/service/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
# Ketut Kumajaya - initial API and implementation and/or initial documentation
# *******************************************************************************/
if(FORTE_WINDOWS_SERVICE)
forte_add_sourcefile_cpp(CppWindowsService.cpp)
forte_add_sourcefile_hcpp(SampleService ServiceBase ServiceInstaller)
forte_add_sourcefile_h(ThreadPool.h)
forte_add_to_executable_h(SampleService ServiceBase ServiceInstaller ThreadPool)
forte_add_to_executable_cpp(CppWindowsService SampleService ServiceBase ServiceInstaller)
endif()
99 changes: 86 additions & 13 deletions src/arch/win32/service/CppWindowsService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* Project: CppWindowsService
* Copyright (c) Microsoft Corporation.
*
* 2024, Ketut Kumajaya - modified for FORTE to run as a Windows service
*
* The file defines the entry point of the application. According to the
* arguments in the command line, the function installs or uninstalls or
* starts the service by calling into different routines.
Expand All @@ -17,23 +19,30 @@
\***************************************************************************/

#pragma region Includes
#include <stdio.h>
#include <cstdio>
#include <windows.h>
#include "ServiceInstaller.h"
#include "ServiceBase.h"
#include "SampleService.h"
#pragma endregion


#include <filesystem>
#include "../../devlog.h"
#include "../../forte_stringFunctions.h"

int _main(int argc, char *arg[]);


//
// Settings of the service
//

// Internal name of the service
#define SERVICE_NAME (PWSTR)L"CppWindowsService"
#define SERVICE_NAME (PWSTR)L"4diac-forte"

// Displayed name of the service
#define SERVICE_DISPLAY_NAME (PWSTR)L"CppWindowsService Sample Service"
#define SERVICE_DISPLAY_NAME (PWSTR)L"4diac FORTE Runtime for Windows"

// Service start options.
#define SERVICE_START_TYPE SERVICE_DEMAND_START
Expand All @@ -48,6 +57,26 @@
#define SERVICE_PASSWORD NULL


// User can edit forte command line arguments in
// HKLM\SYSTEM\CurrentControlSet\Services\4diac-forte\ImagePath
static void convertArguments(int argc, wchar_t *argw[], std::vector<std::string> &args)
{
for (int i = 0; i < argc; ++i)
{
std::string str = forte_wstringToString(argw[i]);
args.push_back(str);
if (str.compare("-service") == 0 || str.compare("-s") == 0)
{
if ((argc & 1) == 0) // forte always expect an argument pair
{
// log redirection enabled by default
args.push_back("log");
}
}
}
}


//
// FUNCTION: wmain(int, wchar_t *[])
//
Expand All @@ -65,6 +94,20 @@
//
int wmain(int argc, wchar_t *argv[])
{
int ret = -1;

// Convert command line arguments from wide to narrow string
std::vector<std::string> l_argvBuff;
convertArguments(argc, argv, l_argvBuff);

// Reconstruct command line arguments fort FORTE process
std::vector<const char*> l_argv;
for (size_t i = 0; i < l_argvBuff.size(); ++i)
{
// Pointer to string
l_argv.push_back(l_argvBuff[i].data());
}

if ((argc > 1) && ((*argv[1] == L'-' || (*argv[1] == L'/'))))
{
if (_wcsicmp(L"install", argv[1] + 1) == 0)
Expand All @@ -86,19 +129,49 @@ int wmain(int argc, wchar_t *argv[])
// "-remove" or "/remove".
UninstallService(SERVICE_NAME);
}
}
else
{
wprintf(L"Parameters:\n");
wprintf(L" -install to install the service.\n");
wprintf(L" -remove to remove the service.\n");
else if (_wcsicmp(L"service", argv[1] + 1) == 0 || _wcsicmp(L"s", argv[1] + 1) == 0)
{
CSampleService service(SERVICE_DISPLAY_NAME, static_cast<int>(l_argv.size()), (char **)l_argv.data());

// Start setup stdout/stderr redirection
wchar_t szPath[MAX_PATH];
if (GetModuleFileNameW(NULL, szPath, ARRAYSIZE(szPath)) == 0) {
DEVLOG_ERROR("GetModuleFileNameW failed w/err 0x%08lx\n", GetLastError());
}

CSampleService service(SERVICE_NAME);
if (!CServiceBase::Run(service))
std::filesystem::path fullpath(szPath);
// Disable logging with "-service nolog" argument
if (std::filesystem::exists(fullpath) && _wcsicmp(L"nolog", argv[2]) != 0) {
auto path = fullpath.replace_extension("log");
std::string logfile = forte_wstringToString(path);
service.StartLogRedirection(logfile.c_str(), stdout);
path = fullpath.replace_extension("err");
logfile = forte_wstringToString(path);
service.StartLogRedirection(logfile.c_str(), stderr);
}

if (!CServiceBase::Run(service))
{
DEVLOG_ERROR("Service failed to run w/err 0x%08lx\n", GetLastError());
}

// Stop stdout/stderr redirection in reverse order
service.StopLogRedirection(stderr);
service.StopLogRedirection(stdout);
}
else
{
wprintf(L"Service failed to run w/err 0x%08lx\n", GetLastError());
ret = _main(static_cast<int>(l_argv.size()), (char **)l_argv.data());
}
}
else
{
ret = _main(static_cast<int>(l_argv.size()), (char **)l_argv.data());
}

// Clear the char vector and then the string vector
l_argv.clear();
l_argvBuff.clear();

return 0;
return ret;
}
Loading

0 comments on commit b5089e4

Please sign in to comment.