Implemented support for setting the Windows Service description
This commit is contained in:
@@ -83,7 +83,7 @@ namespace Duplicati.WindowsService
|
||||
//The path can also include arguments for an auto-start service. For example, "d:\myshare\myservice.exe arg1 arg2". These arguments are passed to the service entry point (typically the main function).
|
||||
try
|
||||
{
|
||||
ServiceInstaller.InstallService(ServiceControl.SERVICE_NAME, ServiceControl.DISPLAY_NAME, "\"" + selfexec + "\"" + " " + commandline);
|
||||
ServiceInstaller.InstallService(ServiceControl.SERVICE_NAME, ServiceControl.DISPLAY_NAME, ServiceControl.SERVICE_DESCRIPTION, "\"" + selfexec + "\"" + " " + commandline);
|
||||
Console.WriteLine("Duplicati service installation succeeded.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -95,7 +95,7 @@ namespace Duplicati.WindowsService
|
||||
}
|
||||
else
|
||||
{
|
||||
ServiceBase.Run(new ServiceBase[] { new ServiceControl(args) });
|
||||
ServiceBase.Run([new ServiceControl(args)]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
using Duplicati.Service;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace Duplicati.WindowsService
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
public class ServiceControl : System.ServiceProcess.ServiceBase
|
||||
{
|
||||
private const string LOG_SOURCE = "Duplicati";
|
||||
private const string LOG_NAME = "Application";
|
||||
public const string SERVICE_NAME = "Duplicati";
|
||||
public const string DISPLAY_NAME = "Duplicati service";
|
||||
public const string SERVICE_DESCRIPTION = "Duplicati running as a Windows Service";
|
||||
|
||||
private readonly System.Diagnostics.EventLog m_eventLog;
|
||||
|
||||
@@ -46,12 +46,13 @@ namespace Duplicati.WindowsService
|
||||
{
|
||||
this.ServiceName = SERVICE_NAME;
|
||||
|
||||
m_eventLog = new System.Diagnostics.EventLog();
|
||||
if (!System.Diagnostics.EventLog.SourceExists(LOG_SOURCE))
|
||||
System.Diagnostics.EventLog.CreateEventSource(LOG_SOURCE, LOG_NAME);
|
||||
|
||||
m_eventLog.Source = LOG_SOURCE;
|
||||
m_eventLog.Log = LOG_NAME;
|
||||
m_eventLog = new System.Diagnostics.EventLog
|
||||
{
|
||||
Source = LOG_SOURCE,
|
||||
Log = LOG_NAME
|
||||
};
|
||||
m_verbose_messages = args != null && args.Any(x => string.Equals("--debug-service", x, StringComparison.OrdinalIgnoreCase));
|
||||
m_cmdargs = (args ?? new string[0]).Where(x => !string.Equals("--debug-service", x, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
|
||||
@@ -78,7 +79,7 @@ namespace Duplicati.WindowsService
|
||||
|
||||
if (m_verbose_messages)
|
||||
m_eventLog.WriteEntry("Starting...");
|
||||
lock(m_lock)
|
||||
lock (m_lock)
|
||||
if (m_runner == null)
|
||||
{
|
||||
if (m_verbose_messages)
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Text;
|
||||
|
||||
namespace Duplicati.WindowsService
|
||||
{
|
||||
@@ -48,6 +46,18 @@ namespace Duplicati.WindowsService
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool DeleteService(IntPtr hService);
|
||||
|
||||
private const int SERVICE_CONFIG_DESCRIPTION = 0x01;
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_DESCRIPTION lpInfo);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct SERVICE_DESCRIPTION
|
||||
{
|
||||
public string lpDescription;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to the service. Before granting the requested access, the
|
||||
/// system checks the access token of the calling process.
|
||||
@@ -391,21 +401,30 @@ namespace Duplicati.WindowsService
|
||||
GENERIC_ALL = SC_MANAGER_ALL_ACCESS,
|
||||
}
|
||||
|
||||
public static void InstallService(string ServiceName, string DisplayName, string Path)
|
||||
public static void InstallService(string ServiceName, string DisplayName, string Description, string Path)
|
||||
{
|
||||
var scMgrHandle = OpenSCManager(null, null, (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
|
||||
|
||||
try
|
||||
{
|
||||
if (scMgrHandle == IntPtr.Zero)
|
||||
throw new Exception($"Win32 error { Marshal.GetLastWin32Error().ToString() } during install service (OpenSCManager)");
|
||||
|
||||
throw new Exception($"Win32 error {Marshal.GetLastWin32Error().ToString()} during install service (OpenSCManager)");
|
||||
|
||||
var serviceHandle = CreateService(scMgrHandle, ServiceName, DisplayName, (uint)SERVICE_ACCESS.SERVICE_ALL_ACCESS, (uint)SERVICE_TYPE.SERVICE_WIN32_OWN_PROCESS,
|
||||
(uint)SERVICE_START.SERVICE_AUTO_START, (uint)SERVICE_ERROR.SERVICE_ERROR_NORMAL, Path, null, null, null, null, null);
|
||||
|
||||
if (serviceHandle == IntPtr.Zero)
|
||||
throw new Exception($"Win32 error { Marshal.GetLastWin32Error().ToString() } during install service (CreateService)");
|
||||
|
||||
throw new Exception($"Win32 error {Marshal.GetLastWin32Error().ToString()} during install service (CreateService)");
|
||||
|
||||
var pinfo = new SERVICE_DESCRIPTION
|
||||
{
|
||||
lpDescription = Description
|
||||
};
|
||||
|
||||
var res = ChangeServiceConfig2(serviceHandle, SERVICE_CONFIG_DESCRIPTION, ref pinfo);
|
||||
if (!res)
|
||||
System.Diagnostics.Trace.WriteLine($"Failed to set decription: {Marshal.GetLastWin32Error().ToString()}");
|
||||
|
||||
CloseServiceHandle(serviceHandle);
|
||||
}
|
||||
finally
|
||||
@@ -421,17 +440,17 @@ namespace Duplicati.WindowsService
|
||||
try
|
||||
{
|
||||
if (scMgrHandle == IntPtr.Zero)
|
||||
throw new Exception($"Win32 error { Marshal.GetLastWin32Error().ToString() } during delete service (OpenSCManager)");
|
||||
throw new Exception($"Win32 error {Marshal.GetLastWin32Error().ToString()} during delete service (OpenSCManager)");
|
||||
|
||||
var serviceHandle = OpenService(scMgrHandle, ServiceName, (uint)SERVICE_ACCESS.SERVICE_ALL_ACCESS);
|
||||
|
||||
if (serviceHandle == IntPtr.Zero)
|
||||
throw new Exception($"Win32 error { Marshal.GetLastWin32Error().ToString() } during delete service (OpenService)");
|
||||
throw new Exception($"Win32 error {Marshal.GetLastWin32Error().ToString()} during delete service (OpenService)");
|
||||
|
||||
try
|
||||
{
|
||||
if (DeleteService(serviceHandle) == false)
|
||||
throw new Exception($"Win32 error { Marshal.GetLastWin32Error().ToString() } during delete service (DeleteService)");
|
||||
throw new Exception($"Win32 error {Marshal.GetLastWin32Error().ToString()} during delete service (DeleteService)");
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user