When we create a Windows service, we find that the service we created has no relevant description. (You can open the Service Manager program to view ). The related classes system. serviceprocess. servicebase do not provide such information. Similarly, if we need to add an appropriate description to our service, we can only process it through unmanaged code.
Using system;
Using system. runtime. interopservices;
Namespace filewatchservice
{
Public class modapi
{
[Dllimport ("advapi32.dll")]
Public static extern int lockservicedatabase (INT hscmanager );
[Dllimport ("advapi32.dll")]
Public static extern bool unlockservicedatabase (INT hscmanager );
[Dllimport ("kernel32.dll")]
Public static extern void copymemory (intptr pdst, SC _action [] psrc, int bytelen );
[Dllimport ("advapi32.dll")]
Public static extern bool changeserviceconfiga (
Int hservice, servicetype dwservicetype, int dwstarttype,
Int dwerrorcontrol, string lpbinarypathname, string lploadordergroup,
Int lpdwtagid, string lpdependencies, string lpservicestartname,
String lppassword, string lpdisplayname );
[Dllimport ("advapi32.dll")]
Public static extern bool changeserviceconfig2a (
Int hservice, infolevel dwinfolevel,
[Financialas (unmanagedtype. struct)] ref service_description lpinfo );
[Dllimport ("advapi32.dll")]
Public static extern bool changeserviceconfig2a (
Int hservice, infolevel dwinfolevel,
[Financialas (unmanagedtype. struct)] ref service_failure_actions lpinfo );
[Dllimport ("advapi32.dll")]
Public static extern int openservicea (
Int hscmanager, string lpservicename, access_type dwdesiredaccess );
[Dllimport ("advapi32.dll")]
Public static extern int openscmanagera (
String lpmachinename, string lpdatabasename, servicecontrolmanagertype dwdesiredaccess );
[Dllimport ("advapi32.dll")]
Public static extern bool closeservicehandle (
Int hscobject );
[Dllimport ("advapi32.dll")]
Public static extern bool queryserviceconfiga (
Int hservice, [financialas (unmanagedtype. struct)] ref query_service_config lpserviceconfig, int cbbufsize,
Int pcbbytesneeded );
[Dllimport ("advapi32.dll")]
Public static extern int startservice (INT svhandle, int dwnumserviceargs, string lpserviceargvectors );
Public const int standard_rights_required = 0xf0000;
Public const int generic_read =-2147483648;
Public const int error_insufficient_buffer = 122;
Public const int service_no_change =-1;
// Public const int service_no_change = 0 xFFFF;
Public Enum servicetype
{
Service_kernel_driver = 0x1,
Service_file_system_driver = 0x2,
Service_win32_own_process = 0x10,
Service_win32_assist_process = 0x20,
Service_interactive_process = 0x100,
Servicetype_no_change = service_no_change
}
Public Enum servicestarttype: int
{
Service_boot_start = 0x0,
Service_system_start = 0x1,
Service_auto_start = 0x2,
Service_demand_start = 0x3,
Service_disabled = 0x4,
Servicestarttype_no_change = service_no_change
}
Public Enum serviceerrorcontrol: int
{
Service_error_ignore = 0x0,
Service_error_normal = 0x1,
Service_error_severe = 0x2,
Service_error_critical = 0x3,
Msidbserviceinstallerrorcontrolv133 = 0x8000,
Serviceerrorcontrol_no_change = service_no_change
}
Public Enum servicestaterequest: int
{
Service_active = 0x1,
Service_inactive = 0x2,
Service_state_all = (service_active + service_inactive)
}
Public Enum servicecontroltype: int
{
Service_control_stop = 0x1,
Service_control_pause = 0x2,
Service_control_continue = 0x3,
Service_control_interrogate = 0x4,
Service_control_shutdown = 0x5,
Service_control_paramchange = 0x6,
Service_control_netbindadd = 0x7,
Service_control_netbindremove = 0x8,
Service_control_netbindenable = 0x9,
Service_control_netbinddisable = 0xa,
Service_control_deviceevent = 0xb,
Service_control_hardwareprofilechange = 0xc,
Service_control_powerevent = 0xd,
Service_control_sessionchange = 0xe,
}
Public Enum servicestate: int
{
Service_stopped = 0x1,
Service_start_pending = 0x2,
Service_stop_pending = 0x3,
Service_running = 0x4,
Service_continue_pending = 0x5,
Service_pause_pending = 0x6,
Service_paused = 0x7,
}
Public Enum servicecontrolaccepted: int
{
Service_accept_stop = 0x1,
Service_accept_pause_continue = 0x2,
Service_accept_shutdown = 0x4,
Service_accept_paramchange = 0x8,
Service_accept_netbindchange = 0x10,
Service_accept_hardwareprofilechange = 0x20,
Service_accept_powerevent = 0x40,
Service_accept_sessionchange = 0x80
}
Public Enum servicecontrolmanagertype: int
{
SC _manager_connect = 0x1,
SC _manager_create_service = 0x2,
SC _manager_enumerate_service = 0x4,
SC _manager_lock = 0x8,
SC _manager_query_lock_status = 0x10,
SC _manager_modify_boot_config = 0x20,
SC _manager_all_access = standard_rights_required + SC _manager_connect + SC _manager_create_service + balance + SC _manager_lock + SC _manager_query_lock_status + SC _manager_modify_boot_config
}
Public Enum access_type: int
{
Service_query_config = 0x1,
Service_change_config = 0x2,
Service_query_status = 0x4,
Service_enumerate_dependents = 0x8,
Service_start = 0x10,
Service_stop = 0x20,
Service_pause_continue = 0x40,
Service_interrogate = 0x80,
Service_user_defined_control = 0x100,
Service_all_access = Response + service_query_config + service_change_config + service_query_status + service_enumerate_dependents + service_start + service_stop + service_pause_continue + service_interrogate + service_user_defined_control
}
[Structlayout (layoutkind. Sequential)]
Public struct service_status
{
Public int dwservicetype;
Public int dwcurrentstate;
Public int dwcontrolsaccepted;
Public int dwwin32exitcode;
Public int dwservicespecificexitcode;
Public int dwcheckpoint;
Public int dwwaithint;
}
[Structlayout (layoutkind. Sequential)]
Public struct query_service_config
{
Public int dwservicetype;
Public int dwstarttype;
Public int dwerrorcontrol;
Public String lpbinarypathname;
Public String lploadordergroup;
Public int dwtagid;
Public String lpdependencies;
Public String lpservicestartname;
Public String lpdisplayname;
}
Public Enum SC _action_type: int
{
SC _action_none = 0,
SC _action_restart = 1,
SC _action_reboot = 2,
SC _action_run_command = 3,
}
[Structlayout (layoutkind. Sequential)]
Public struct SC _action
{
Public SC _action_type scactiontype;
Public int delay;
}
Public Enum infolevel: int
{
Service_config_description = 1,
Service_config_failure_actions = 2
}
[Structlayout (layoutkind. Sequential)]
Public struct service_description
{
Public String lpdescription;
}
[Structlayout (layoutkind. Sequential)]
Public struct service_failure_actions
{
Public int dwresetperiod;
Public String lprebootmsg;
Public String lpcommand;
Public int cactions;
Public int lpsaactions;
}
}
}
When we add an installation package to the service, we can add the code for modifying the service description in projectinstaller.
Private void initializecomponent ()
{
// Add code here
This. afterinstall + = new system. configuration. Install. installeventhandler (this. projectinstaller_afterinstall );
}
Private void projectinstaller_afterinstall (Object sender, system. configuration. Install. installeventargs E)
{
Int iscmanagerhandle = 0;
Int iscmanagerlockhandle = 0;
Int iservicehandle = 0;
Bool bchangeserviceconfig = false;
Bool bchangeserviceconfig2 = false;
Modapi. service_description servicedescription;
Modapi. service_failure_actions servicefailureactions;
Modapi. SC _action [] scactions = new modapi. SC _action [3];
Bool bcloseservice = false;
Bool bunlockscmanager = false;
Bool bclosescmanager = false;
Intptr iscactionspointer = new intptr ();
Try
{
// Open the Service Console
Iscmanagerhandle = modapi. openscmanagera (null, null,
Modapi. servicecontrolmanagertype. SC _manager_all_access );
If (iscmanagerhandle <1)
{
Throw new exception ("Service Manager cannot be opened .");
}
Iscmanagerlockhandle = modapi. lockservicedatabase (iscmanagerhandle );
If (iscmanagerlockhandle <1)
{
Throw new exception ("Service Manager cannot be locked .");
}
// Service name
Iservicehandle = modapi. openservicea (iscmanagerhandle, "jadewatchservice ",
Modapi. access_type.service_all_access );
If (iservicehandle <1)
{
Throw new exception ("the service cannot be opened for modification .");
}
Bchangeserviceconfig = modapi. changeserviceconfiga (iservicehandle,
Modapi. servicetype. service_win32_own_process | modapi. servicetype. service_interactive_process,
Modapi. service_no_change, modapi. service_no_change, null, null,
0, null, null );
If (bchangeserviceconfig = false)
{
Throw new exception ("service settings cannot be changed .");
}
Servicedescription. lpdescription = "qingniao file monitoring service. If you stop this service, data cannot be properly backed up! ";
Bchangeserviceconfig2 = modapi. changeserviceconfig2a (iservicehandle,
Modapi. infolevel. service_config_description, ref servicedescription );
If (bchangeserviceconfig2 = false)
{
Throw new exception ("service description changes cannot be made .");
}
Servicefailureactions. dwresetperiod = 600;
Servicefailureactions. lprebootmsg = "service startup failed! Restarting ...";
// Servicefailureactions. lpcommand = "somecommand.exe param1 param2 ";
Servicefailureactions. lpcommand = "";
Servicefailureactions. cactions = scactions. length;
// Fault recovery settings, which are not set here
Scactions [0]. Delay = 20000;
Scactions [0]. scactiontype = modapi. SC _action_type. SC _action_none; // do not process failed operations. if the service is restarted
Scactions [1]. Delay = 20000;
Scactions [1]. scactiontype = modapi. SC _action_type. SC _action_none;
Scactions [2]. Delay = 20000;
Scactions [2]. scactiontype = modapi. SC _action_type. SC _action_none;
Iscactionspointer = marshal. allochglobal (marshal. sizeof (New modapi. SC _action () * 3 );
Modapi. copymemory (iscactionspointer, scactions, Marshal. sizeof (New modapi. SC _action () * 3 );
Servicefailureactions. lpsaactions = iscactionspointer. toint32 ();
Bchangeserviceconfig2 = modapi. changeserviceconfig2a (iservicehandle,
Modapi. infolevel. service_config_failure_actions, ref servicefailureactions );
If (bchangeserviceconfig2 = false)
{
Throw new exception ("Failure Recovery Settings cannot be set for the service .");
}
}
Catch (exception ex)
{
Throw new exception (ex. Message );
}
Finally
{
Marshal. freehglobal (iscactionspointer );
If (iservicehandle> 0)
{
Bcloseservice = modapi. closeservicehandle (iservicehandle );
}
If (iscmanagerlockhandle> 0)
{
Bunlockscmanager = modapi. unlockservicedatabase (iscmanagerlockhandle );
}
If (iscmanagerhandle! = 0)
{
Bclosescmanager = modapi. closeservicehandle (iscmanagerhandle );
}
}
}
After the installation is complete, we perform the service. The content that can be modified here includes the service description and service fault handling.
If you need to automatically run the service during installation or uninstall the service, you only need to register
This. beforeuninstall + = new installeventhandler (projectinstaller_beforeuninstall );
This. Committed + = new installeventhandler (projectinstaller_committed );
These two events
Committed event. Here, you can adjust the installed services to the running status.
Beforeuninstall event, where you can automatically uninstall the service