aboutsummaryrefslogtreecommitdiff
path: root/src/zen/cmds/service_cmd.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2025-01-08 13:49:56 +0100
committerDan Engelbrecht <[email protected]>2025-01-08 13:49:56 +0100
commit995aec217bbb26c9c2a701cc77edb067ffbf8d36 (patch)
tree2da2d3fd806547bd9f38bc190514abbf9fdb6361 /src/zen/cmds/service_cmd.cpp
parentcheck if service is already installed before attempting install (diff)
downloadarchived-zen-995aec217bbb26c9c2a701cc77edb067ffbf8d36.tar.xz
archived-zen-995aec217bbb26c9c2a701cc77edb067ffbf8d36.zip
add ServiceLevel for service processes: User, AllUsers and Service
Diffstat (limited to 'src/zen/cmds/service_cmd.cpp')
-rw-r--r--src/zen/cmds/service_cmd.cpp129
1 files changed, 103 insertions, 26 deletions
diff --git a/src/zen/cmds/service_cmd.cpp b/src/zen/cmds/service_cmd.cpp
index aede68573..7727ed8a2 100644
--- a/src/zen/cmds/service_cmd.cpp
+++ b/src/zen/cmds/service_cmd.cpp
@@ -120,6 +120,12 @@ ServiceCommand::ServiceCommand()
m_StatusOptions.positional_help("name");
m_InstallOptions.add_options()("h,help", "Print help");
+ m_InstallOptions.add_option("",
+ "l",
+ "service-level",
+ "Service level: CurrentUser, AllUsers, System. Default is CurrentUser",
+ cxxopts::value(m_ServiceLevel),
+ "<level>");
m_InstallOptions.add_option("", "s", "executable", "Path to server executable", cxxopts::value(m_ServerExecutable), "<path>");
m_InstallOptions.add_option("",
"n",
@@ -209,19 +215,29 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
ZEN_CONSOLE("Can't get information about service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
return 1;
}
- ZEN_CONSOLE(
- "Service '{}':\n"
- " Status: {}\n"
- " Executable: {}\n"
- " CommandLineOptions: {}\n"
- " Display Name: {}\n"
- " Description: {}",
- m_ServiceName,
- ToString(Info.Status),
- Info.Spec.ExecutablePath,
- Info.Spec.CommandLineOptions,
- Info.Spec.DisplayName,
- Info.Spec.Description);
+ if (Info.Status == ServiceStatus::NotInstalled)
+ {
+ ZEN_CONSOLE("Service '{}' is not installed", m_ServiceName);
+ return 0;
+ }
+ else
+ {
+ ZEN_CONSOLE(
+ "Service '{}':\n"
+ " Status: {}\n"
+ " Level: {}\n"
+ " Executable: {}\n"
+ " CommandLineOptions: {}\n"
+ " Display Name: {}\n"
+ " Description: {}",
+ m_ServiceName,
+ ToString(Info.Status),
+ ToString(Info.Spec.ServiceLevel),
+ Info.Spec.ExecutablePath,
+ Info.Spec.CommandLineOptions,
+ Info.Spec.DisplayName,
+ Info.Spec.Description);
+ }
}
if (SubOption == &m_InstallOptions)
@@ -233,12 +249,14 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
ZEN_CONSOLE(
"Service '{}' already installed:\n"
" Status: {}\n"
+ " Level: {}\n"
" Executable: {}\n"
" CommandLineOptions: {}\n"
" Display Name: {}\n"
" Description: {}",
m_ServiceName,
ToString(Info.Status),
+ ToString(Info.Spec.ServiceLevel),
Info.Spec.ExecutablePath,
Info.Spec.CommandLineOptions,
Info.Spec.DisplayName,
@@ -246,8 +264,18 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
return 1;
}
+ std::optional<ServiceLevel> Level = ServiceLevel::CurrentUser;
+ if (!m_ServiceLevel.empty())
+ {
+ Level = FromString(m_ServiceLevel);
+ }
+ if (!Level.has_value())
+ {
+ throw zen::OptionParseException("invalid service level");
+ }
+
#if ZEN_PLATFORM_WINDOWS
- if (!WinIsElevated())
+ if (!WinIsElevated() && (Level.value() != ServiceLevel::CurrentUser))
{
return WinRelaunchElevated();
}
@@ -259,12 +287,12 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
m_ServerExecutable = ExePath;
}
m_ServerExecutable = std::filesystem::absolute(m_ServerExecutable);
-
- Ec = InstallService(m_ServiceName,
- ServiceSpec{.ExecutablePath = m_ServerExecutable,
- .CommandLineOptions = GlobalOptions.PassthroughCommandLine,
- .DisplayName = m_ServiceDisplayName,
- .Description = m_ServiceDescription});
+ Ec = InstallService(m_ServiceName,
+ ServiceSpec{.ServiceLevel = Level.value(),
+ .ExecutablePath = m_ServerExecutable,
+ .CommandLineOptions = GlobalOptions.PassthroughCommandLine,
+ .DisplayName = m_ServiceDisplayName,
+ .Description = m_ServiceDescription});
if (Ec)
{
ZEN_CONSOLE("Failed to install service '{}' using '{}' . Reason: '{}'", m_ServiceName, m_ServerExecutable, Ec.message());
@@ -275,13 +303,26 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
if (SubOption == &m_UninstallOptions)
{
+ ServiceInfo Info;
+ std::error_code Ec = QueryInstalledService(m_ServiceName, Info);
+ if (Ec)
+ {
+ ZEN_CONSOLE("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
+ return 1;
+ }
+ if (Info.Status == ServiceStatus::NotInstalled)
+ {
+ ZEN_CONSOLE("Service '{}' is not installed", m_ServiceName);
+ return 0;
+ }
+
#if ZEN_PLATFORM_WINDOWS
- if (!WinIsElevated())
+ if (!WinIsElevated() && (Info.Spec.ServiceLevel != ServiceLevel::CurrentUser))
{
return WinRelaunchElevated();
}
#endif // ZEN_PLATFORM_WINDOWS
- std::error_code Ec = UninstallService(m_ServiceName);
+ Ec = UninstallService(m_ServiceName, Info.Spec.ServiceLevel);
if (Ec)
{
ZEN_CONSOLE("Failed to uninstall service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
@@ -292,13 +333,31 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
if (SubOption == &m_StartOptions)
{
+ ServiceInfo Info;
+ std::error_code Ec = QueryInstalledService(m_ServiceName, Info);
+ if (Ec)
+ {
+ ZEN_CONSOLE("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
+ return 1;
+ }
+ if (Info.Status == ServiceStatus::NotInstalled)
+ {
+ ZEN_CONSOLE("Service '{}' is not installed", m_ServiceName);
+ return 1;
+ }
+ if (Info.Status != ServiceStatus::Stopped)
+ {
+ ZEN_CONSOLE("Service '{}' is already running", m_ServiceName);
+ return 1;
+ }
+
#if ZEN_PLATFORM_WINDOWS
- if (!WinIsElevated())
+ if (!WinIsElevated() && (Info.Spec.ServiceLevel != ServiceLevel::CurrentUser))
{
return WinRelaunchElevated();
}
#endif // ZEN_PLATFORM_WINDOWS
- std::error_code Ec = StartService(m_ServiceName);
+ Ec = StartService(m_ServiceName, Info.Spec.ServiceLevel);
if (Ec)
{
ZEN_CONSOLE("Failed to start service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
@@ -309,13 +368,31 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
if (SubOption == &m_StopOptions)
{
+ ServiceInfo Info;
+ std::error_code Ec = QueryInstalledService(m_ServiceName, Info);
+ if (Ec)
+ {
+ ZEN_CONSOLE("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
+ return 1;
+ }
+ if (Info.Status == ServiceStatus::NotInstalled)
+ {
+ ZEN_CONSOLE("Service '{}' is not installed", m_ServiceName);
+ return 1;
+ }
+ if (Info.Status != ServiceStatus::Running)
+ {
+ ZEN_CONSOLE("Service '{}' is not running", m_ServiceName);
+ return 1;
+ }
+
#if ZEN_PLATFORM_WINDOWS
- if (!WinIsElevated())
+ if (!WinIsElevated() && (Info.Spec.ServiceLevel != ServiceLevel::CurrentUser))
{
return WinRelaunchElevated();
}
#endif // ZEN_PLATFORM_WINDOWS
- std::error_code Ec = StopService(m_ServiceName);
+ Ec = StopService(m_ServiceName, Info.Spec.ServiceLevel);
if (Ec)
{
ZEN_CONSOLE("Failed to stop service '{}'. Reason: '{}'", m_ServiceName, Ec.message());