当我们创建一个windows服务后,却发觉我们所创建的服务没有相关的描述。(你可以打开服务管理器程序查看)。而system.serviceprocess.servicebase这些相关的类都没有提供这方面的信息。同样如果我们需要给我们的服务加上恰当的描述,我们也只能通过非托管代码来处理。
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,
[marshalas(unmanagedtype.struct)] ref service_description lpinfo);
[dllimport("advapi32.dll")]
public static extern bool changeserviceconfig2a(
int hservice, infolevel dwinfolevel,
[marshalas(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, [marshalas(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 = 0xffff;
public enum servicetype
{
service_kernel_driver = 0x1,
service_file_system_driver = 0x2,
service_win32_own_process = 0x10,
service_win32_share_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,
msidbserviceinstallerrorcontrolvital = 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 + sc_manager_enumerate_service + 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 = standard_rights_required + 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;
}
}
}
当我们给服务增加安装包时,我们可以在projectinstaller里加上我们修改服务描述的代码
private void initializecomponent()
{
//这里要增加代码
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
{
//打开服务控制台
iscmanagerhandle = modapi.openscmanagera(null, null,
modapi.servicecontrolmanagertype.sc_manager_all_access);
if (iscmanagerhandle < 1)
{
throw new exception("不能打开服务管理器.");
}
iscmanagerlockhandle = modapi.lockservicedatabase(iscmanagerhandle);
if (iscmanagerlockhandle < 1)
{
throw new exception("不能锁定服务管理器.");
}
//服务名
iservicehandle = modapi.openservicea(iscmanagerhandle, "jadewatchservice",
modapi.access_type.service_all_access);
if (iservicehandle < 1)
{
throw new exception("不能打开服务进行修改.");
}
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, null, null);
if (bchangeserviceconfig==false)
{
throw new exception("不能改变服务设置.");
}
servicedescription.lpdescription = "青鸟文件监控服务,如果停止该服务,数据将不能正常进行备份!";
bchangeserviceconfig2 = modapi.changeserviceconfig2a(iservicehandle,
modapi.infolevel.service_config_description,ref servicedescription);
if (bchangeserviceconfig2==false)
{
throw new exception("不能进行服务描述更改.");
}
servicefailureactions.dwresetperiod = 600;
servicefailureactions.lprebootmsg = "服务启动失败! 重启中...";
// servicefailureactions.lpcommand = "somecommand.exe param1 param2";
servicefailureactions.lpcommand = "";
servicefailureactions.cactions = scactions.length;
//故障恢复设置,这里没有设置
scactions[0].delay = 20000;
scactions[0].scactiontype = modapi.sc_action_type.sc_action_none; //不要对失败操作做任何处理,如果重启服务等
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("不能设置服务的故障恢复设置.");
}
}
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);
}
}
}
在安装完成后,我们对服务进行。这里可以修改的内容包括服务的描述,服务的故障处理等.
如果你在安装时,需要对服务进行自动处于运行状态,或卸载时需要自动将服务也卸载,你只要注册
this.beforeuninstall+=new installeventhandler(projectinstaller_beforeuninstall);
this.committed+=new installeventhandler(projectinstaller_committed);
这二个事件
committed事件,在这里可以将安装的服务进行调整到运行状态
beforeuninstall事件,您可以在这里将服务自动卸载掉
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!


