Service description

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

In Computer Management, in the list of services, there is a "Description"
column. How do I set this for my service?

(System.ServiceProcess.ServiceInstaller.DisplayName doesn't do it.)
 
Tricky with VS-generated setup projects:
1. Use ChangeServiceConfig2 (Win32) on your Service.
2. Install it with a tool that uses the normal Windows Installer way of
installing Services (the ServiceInstall table). VS installs Services by
running Installer class custom action code - all the other tools I've ever
seen just let you describe the Service in an IDE and have Windows Installer
do it, including that description you're looking for.
 
Tricky is right. But doable. I added the following to my library...

----------


private const System.Int32 SERVICE_CONFIG_DESCRIPTION = 1 ;
private const System.Int32 SERVICE_CHANGE_CONFIG = 0x0002 ;

private const System.Int32 STANDARD_RIGHTS_REQUIRED =
0x000F0000 ;

private const System.Int32 SC_MANAGER_CONNECT = 0x0001 ;
private const System.Int32 SC_MANAGER_CREATE_SERVICE = 0x0002 ;
private const System.Int32 SC_MANAGER_ENUMERATE_SERVICE = 0x0004 ;
private const System.Int32 SC_MANAGER_LOCK = 0x0008 ;
private const System.Int32 SC_MANAGER_QUERY_LOCK_STATUS = 0x0010 ;
private const System.Int32 SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020 ;

private const System.Int32 SC_MANAGER_ALL_ACCESS =
(
STANDARD_RIGHTS_REQUIRED |
SC_MANAGER_CONNECT |
SC_MANAGER_CREATE_SERVICE |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_LOCK |
SC_MANAGER_QUERY_LOCK_STATUS |
SC_MANAGER_MODIFY_BOOT_CONFIG
) ;

internal struct SERVICE_DESCRIPTION
{
internal System.IntPtr lpDescription ;
}

[System.Runtime.InteropServices.DllImport ( "Advapi32" ,
SetLastError=true , EntryPoint="OpenSCManager" )]
private unsafe static extern System.IntPtr
API_OpenSCManager
(
string lpMachineName
,
string lpDataBaseName
,
int dwDesiredAccess
) ;

[System.Runtime.InteropServices.DllImport ( "Advapi32" ,
SetLastError=true , EntryPoint="OpenService" )]
private unsafe static extern System.IntPtr
API_OpenService
(
System.IntPtr hSCManager
,
string lpServiceName
,
int dwDesiredAccess
) ;

[System.Runtime.InteropServices.DllImport ( "Advapi32" ,
SetLastError=true , EntryPoint="CloseServiceHandle" )]
private unsafe static extern bool
API_CloseServiceHandle
(
System.IntPtr hSCObject
) ;

[System.Runtime.InteropServices.DllImport ( "Advapi32" ,
SetLastError=true , EntryPoint="ChangeServiceConfig2" )]
private unsafe static extern bool
API_ChangeServiceConfig2
(
System.IntPtr hService
,
int dwInfoLevel
,
System.IntPtr lpInfo
) ;

public unsafe static bool
SetServiceDescription
(
string ServiceName
,
string Description
)
{
bool result = false ;
int InfoLevel = SERVICE_CONFIG_DESCRIPTION ;
byte* temp = stackalloc byte [ Description.Length+1 ] ;

for ( int runner = 0 ; runner < Description.Length ; runner++ )
{
temp [ runner] = (byte) Description [ runner ] ;
}
temp [ Description.Length ] = 0 ;

SERVICE_DESCRIPTION Info ;
Info.lpDescription = new System.IntPtr ( temp ) ;

System.IntPtr schSCManager = API_OpenSCManager
(
null
,
null
,
SC_MANAGER_ALL_ACCESS
) ;

System.IntPtr hService = API_OpenService
(
schSCManager
,
ServiceName
,
SERVICE_CHANGE_CONFIG
) ;

result = API_ChangeServiceConfig2
(
hService
,
InfoLevel
,
new System.IntPtr ( &Info )
) ;

API_CloseServiceHandle
(
hService
) ;

return ( result ) ;
}

----------

Then in my ServiceThread class I added...

public void
AfterInstallEventHandler
(
object sender
,
System.Configuration.Install.InstallEventArgs e
)
{
PIEBALD.Lib.LibAPI.SetServiceDescription ( this.ServiceName ,
this.description ) ;
}

----------

And in my ServiceInstaller class I added...

serviceInstaller.AfterInstall += new
System.Configuration.Install.InstallEventHandler
( srv.AfterInstallEventHandler ) ;
 
Here's how I did it. I added a Value named 'Description' in the Key under:

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services

that is named after my service name; i.e. the ServiceName property of my
Service class. So if your service is named 'TestSvc' add a the Value
'Description' under the Key
'HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\TestSvc' when you install
the service. The data for the value is the description that appears in the
Services control panel applet for your service.
I put the code for doing this in the AfterInstall event of the
ServiceInstaller for my service, so for TestSvc:

Dim regKey As Microsoft.Win32.RegistryKey =
Microsoft.Win32.Registry.LocalMachine.CreateSubKey("SYSTEM\ControlSet001\Services\TestSvc")

regKey.SetValue("Description", "Service To Test adding a Description
to a Service.")

[A Caveat to this is that there is, in my registry, also a CurrentControlSet
key and a ControlSet003 Key that contain a list of services, the
CurrentControlSet I presume to be the current profile running, which could be
either of the ControlSet??? Keys depending on the profile that is being used.
The description may not be transferred and therefore shown under a different
profile. This is not a situation I can ever see me getting into so I haven't
tested it.]

This seemed to me to be a strange ommision from the .Net class. Perhaps
someone is listening and will implement it in the next version of .Net; if it
is .Net by then.
 
Back
Top