/// <summary>
/// Installs and optionally starts the service.
/// </summary>
/// <param name="path">The full path of the service exe.</param>
/// <param name="name">The name of the service.</param>
/// <param name="displayName">The display name of the service.</param>
/// <param name="description">The description for the service.</param>
/// <param name="startMode">The service start mode.</param>
/// <param name="userName">The account name. Null to use the default account (LocalSystem).</param>
/// <param name="password">The account password.</param>
/// <param name="start">True to start the service after the installation; otherwise, false.
/// Once the method returns you can use this parameter to check whether the service is running or not.</param>
/// <param name="dependencies">The list of dependencies services. Null if there are no dependencies.</param>
/// <returns>True for success. Otherwise, false.</returns>
public static bool InstallService(
string path,
string name,
string displayName,
string description,
StartMode startMode,
string userName,
string password,
ref bool start,
string[] dependencies)
{
uint SC_MANAGER_CREATE_SERVICE = 0x0002;
if (string.IsNullOrEmpty(userName))
{
userName = null;
password = null;
}
// check if an existing service needs to uninstalled.
try
{
Service existingService = ServiceManager.GetService(name);
if (existingService != null)
{
if (existingService.StartMode != StartMode.Disabled && existingService.Path == path)
{
if (existingService.Status == ServiceStatus.Stopped)
{
ServiceManager.StartService(name);
}
return(true);
}
UnInstallService(name);
}
}
catch (Exception e)
{
Utils.Trace(e, "CreateService Exception");
}
IntPtr svHandle = IntPtr.Zero;
try
{
IntPtr scHandle = OpenSCManagerW(null, null, SC_MANAGER_CREATE_SERVICE);
if (scHandle.ToInt64() != 0)
{
string dependencyServices = string.Empty;
if (dependencies != null && dependencies.Length > 0)
{
for (int i = 0; i < dependencies.Length; i++)
{
if (!string.IsNullOrEmpty(dependencies[i]))
{
dependencyServices += dependencies[i].Trim();
if (i < dependencies.Length - 1)
{
dependencyServices += "\0";//add a null char separator
}
}
}
}
if (dependencyServices == string.Empty)
{
dependencyServices = null;
}
// lpDependencies, if not null, must be a series of strings concatenated with the null character as a delimiter, including a trailing one.
svHandle = CreateServiceW(
scHandle,
name,
displayName,
(uint)ServiceAccess.AllAccess,
(uint)ServiceType.OwnProcess,
(uint)startMode,
(uint)ServiceError.ErrorNormal,
path,
null,
0,
dependencyServices,
userName,
password);
if (svHandle.ToInt64() == 0)
{
int error = GetLastError();
Utils.Trace("CreateService Error: {0}", error);
return(false);
}
// set the description.
if (!String.IsNullOrEmpty(description))
{
SERVICE_DESCRIPTION info = new SERVICE_DESCRIPTION();
info.lpDescription = description;
IntPtr pInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(SERVICE_DESCRIPTION)));
Marshal.StructureToPtr(info, pInfo, false);
try
{
int result = ChangeServiceConfig2W(svHandle, SERVICE_CONFIG_DESCRIPTION, pInfo);
if (result == 0)
{
Utils.Trace("Could not set description for service: {0}", displayName);
}
}
finally
{
Marshal.DestroyStructure(pInfo, typeof(SERVICE_DESCRIPTION));
Marshal.FreeCoTaskMem(pInfo);
}
}
// start the service.
if (start)
{
start = ServiceManager.StartService(name, new TimeSpan(0, 0, 0, 60));
}
return(true);
}
}
catch (Exception e)
{
Utils.Trace(e, "CreateService Exception");
}
finally
{
SafeCloseServiceHandle(svHandle);
}
return(false);
}