WIP: adding windows service

This commit is contained in:
Naim A 2016-01-31 04:45:03 +02:00
parent 465f942baf
commit 7271aa2cb0
5 changed files with 265 additions and 5 deletions

View file

@ -31,6 +31,7 @@
#include "http/httpserver.hpp" #include "http/httpserver.hpp"
#include "http/webapp.hpp" #include "http/webapp.hpp"
#include "tracker.hpp" #include "tracker.hpp"
#include "service.hpp"
UDPT::Logger *logger = NULL; UDPT::Logger *logger = NULL;
@ -83,6 +84,9 @@ int main(int argc, char *argv[])
("config,c", boost::program_options::value<std::string>()->default_value("/etc/udpt.conf"), "configuration file to use") ("config,c", boost::program_options::value<std::string>()->default_value("/etc/udpt.conf"), "configuration file to use")
#ifdef linux #ifdef linux
("interactive,i", "doesn't start as daemon") ("interactive,i", "doesn't start as daemon")
#endif
#ifdef WIN32
("service,s", boost::program_options::value<std::string>(), "start/stop/install/uninstall service")
#endif #endif
; ;
@ -109,6 +113,9 @@ int main(int argc, char *argv[])
#ifdef linux #ifdef linux
("daemon.chdir", boost::program_options::value<std::string>()->default_value("/"), "home directory for daemon") ("daemon.chdir", boost::program_options::value<std::string>()->default_value("/"), "home directory for daemon")
#endif
#ifdef WIN32
("service.name", boost::program_options::value<std::string>()->default_value("udpt"), "service name to use")
#endif #endif
; ;
@ -177,6 +184,55 @@ int main(int argc, char *argv[])
} }
::signal(SIGTERM, _signal_handler); ::signal(SIGTERM, _signal_handler);
#endif #endif
#ifdef WIN32
UDPT::Service svc(var_map);
if (var_map.count("service"))
{
const std::string& action = var_map["service"].as<std::string>();
try
{
if ("install" == action)
{
std::cout << "Installing service..." << std::endl;
svc.install();
std::cout << "Installed." << std::endl;
}
else if ("uninstall" == action)
{
std::cout << "Removing service..." << std::endl;
svc.uninstall();
std::cout << "Removed." << std::endl;
}
else if ("start" == action)
{
svc.start();
}
else if ("stop" == action)
{
svc.stop();
}
}
catch (const UDPT::OSError& ex)
{
std::cout << "An operating system error occurred: " << ex.getErrorCode() << std::endl;
return -1;
}
return 0;
}
try
{
svc.setup();
}
catch (const OSError& err)
{
if (ERROR_FAILED_SERVICE_CONTROLLER_CONNECT != err.getErrorCode())
{
logger->log(UDPT::Logger::LL_ERROR, "failed to start as service");
}
}
#endif
tracker.start(var_map); tracker.start(var_map);
tracker.wait(); tracker.wait();

135
src/service.cpp Normal file
View file

@ -0,0 +1,135 @@
/*
* Copyright © 2012-2016 Naim A.
*
* This file is part of UDPT.
*
* UDPT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UDPT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with UDPT. If not, see <http://www.gnu.org/licenses/>.
*/
#include "service.hpp"
#ifdef WIN32
namespace UDPT
{
Service::Service(const boost::program_options::variables_map& conf) : m_conf(conf)
{
}
Service::~Service()
{
}
void Service::install()
{
std::string& binaryPath = getFilename();
binaryPath = "\"" + binaryPath + "\"";
std::shared_ptr<void> svcMgr = getServiceManager(SC_MANAGER_CREATE_SERVICE);
{
SC_HANDLE installedService = ::CreateService(reinterpret_cast<SC_HANDLE>(svcMgr.get()),
m_conf["service.name"].as<std::string>().c_str(),
"UDPT Tracker",
SC_MANAGER_CREATE_SERVICE,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
binaryPath.c_str(),
NULL,
NULL,
NULL,
NULL,
NULL
);
if (nullptr == installedService)
{
throw OSError();
}
::CloseServiceHandle(installedService);
}
}
void Service::uninstall()
{
std::shared_ptr<void> service = getService(DELETE);
BOOL bRes = ::DeleteService(reinterpret_cast<SC_HANDLE>(service.get()));
if (FALSE == bRes)
{
throw OSError();
}
}
void Service::start()
{
}
void Service::stop()
{
}
void Service::setup()
{
SERVICE_TABLE_ENTRY service = { 0 };
service.lpServiceName = const_cast<char*>(m_conf["service.name"].as<std::string>().c_str());
service.lpServiceProc = reinterpret_cast<LPSERVICE_MAIN_FUNCTION>(&Service::serviceMain);
if (FALSE == ::StartServiceCtrlDispatcher(&service))
{
throw OSError();
}
}
VOID Service::serviceMain(DWORD argc, LPCSTR argv[])
{
}
std::shared_ptr<void> Service::getService(DWORD access)
{
std::shared_ptr<void> serviceManager = getServiceManager(access);
{
SC_HANDLE service = ::OpenService(reinterpret_cast<SC_HANDLE>(serviceManager.get()), m_conf["service.name"].as<std::string>().c_str(), access);
if (nullptr == service)
{
throw OSError();
}
return std::shared_ptr<void>(service, ::CloseServiceHandle);
}
}
std::shared_ptr<void> Service::getServiceManager(DWORD access)
{
SC_HANDLE svcMgr = ::OpenSCManager(NULL, NULL, access);
if (nullptr == svcMgr)
{
throw OSError();
}
return std::shared_ptr<void>(svcMgr, ::CloseServiceHandle);
}
std::string Service::getFilename()
{
char filename[MAX_PATH];
DWORD dwRet = ::GetModuleFileName(NULL, filename, sizeof(filename) / sizeof(char));
if (0 == dwRet)
{
throw OSError();
}
return std::string(filename);
}
}
#endif

60
src/service.hpp Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright © 2012-2016 Naim A.
*
* This file is part of UDPT.
*
* UDPT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UDPT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with UDPT. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <boost/program_options.hpp>
#include "multiplatform.h"
#include "exceptions.h"
#ifdef WIN32
namespace UDPT
{
class Service
{
public:
Service(const boost::program_options::variables_map& conf);
virtual ~Service();
void install();
void uninstall();
void start();
void stop();
void setup();
private:
const boost::program_options::variables_map& m_conf;
std::shared_ptr<void> getService(DWORD access);
static VOID WINAPI handler(DWORD controlCode);
static VOID WINAPI serviceMain(DWORD argc, LPCSTR argv[]);
static std::shared_ptr<void> getServiceManager(DWORD access);
static std::string getFilename();
};
}
#endif

View file

@ -59,7 +59,7 @@
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;sqlite3.lib;</AdditionalDependencies> <AdditionalDependencies>ws2_32.lib;sqlite3.lib;advapi32.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -73,10 +73,11 @@
<ExceptionHandling>Async</ExceptionHandling> <ExceptionHandling>Async</ExceptionHandling>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <EnableCOMDATFolding>
<EnableCOMDATFolding>true</EnableCOMDATFolding> </EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>
<AdditionalDependencies>ws2_32.lib;sqlite3.lib;%(AdditionalDependencies)</AdditionalDependencies> </OptimizeReferences>
<AdditionalDependencies>ws2_32.lib;sqlite3.lib;advapi32.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@ -86,6 +87,7 @@
<ClCompile Include="..\..\src\http\webapp.cpp" /> <ClCompile Include="..\..\src\http\webapp.cpp" />
<ClCompile Include="..\..\src\logging.cpp" /> <ClCompile Include="..\..\src\logging.cpp" />
<ClCompile Include="..\..\src\main.cpp" /> <ClCompile Include="..\..\src\main.cpp" />
<ClCompile Include="..\..\src\service.cpp" />
<ClCompile Include="..\..\src\tools.c" /> <ClCompile Include="..\..\src\tools.c" />
<ClCompile Include="..\..\src\tracker.cpp" /> <ClCompile Include="..\..\src\tracker.cpp" />
<ClCompile Include="..\..\src\udpTracker.cpp" /> <ClCompile Include="..\..\src\udpTracker.cpp" />
@ -98,6 +100,7 @@
<ClInclude Include="..\..\src\http\webapp.hpp" /> <ClInclude Include="..\..\src\http\webapp.hpp" />
<ClInclude Include="..\..\src\logging.h" /> <ClInclude Include="..\..\src\logging.h" />
<ClInclude Include="..\..\src\multiplatform.h" /> <ClInclude Include="..\..\src\multiplatform.h" />
<ClInclude Include="..\..\src\service.hpp" />
<ClInclude Include="..\..\src\tools.h" /> <ClInclude Include="..\..\src\tools.h" />
<ClInclude Include="..\..\src\tracker.hpp" /> <ClInclude Include="..\..\src\tracker.hpp" />
<ClInclude Include="..\..\src\udpTracker.hpp" /> <ClInclude Include="..\..\src\udpTracker.hpp" />

View file

@ -54,6 +54,9 @@
<ClCompile Include="..\..\src\tracker.cpp"> <ClCompile Include="..\..\src\tracker.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\service.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\logging.h"> <ClInclude Include="..\..\src\logging.h">
@ -86,5 +89,8 @@
<ClInclude Include="..\..\src\tracker.hpp"> <ClInclude Include="..\..\src\tracker.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\service.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>