设为首页 收藏本站
查看: 1018|回复: 0

[经验分享] C#实现对Windows 服务安装

[复制链接]

尚未签到

发表于 2017-6-29 09:49:17 | 显示全部楼层 |阅读模式
  Windows服务作用:定时用户消息推送,WEB程序实时统计等
  Windows服务创建:C#创建服务的方式也有很多种,建议大家在做之前可以先全面了解一下这方面东西再去动手这样便于解决中间遇到一些比较棘手的小问题。
  主要说一种通过SC命令实现服务的创建、修改、查询、卸载、开始、暂停,具体服务工作的业务可以另行完善。
  1,创建一个控制台程序,当然也可以写个winform或者其他XXX
DSC0000.png

  2,在创建好的项目中新建一个服务
DSC0001.png

  创建完服务,剩下的就需要代码实现了。
  思路:我们将通过模拟在命令窗中输入SC服务命令创建和操作服务,所以这里先把一些公用的方法写出来。
  运行命令并返回命令输出消息



/// <summary>
/// 运行CMD命令
/// </summary>
/// <param name="cmd">命令</param>
/// <returns></returns>
public static string Cmd(string[] cmd)
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.AutoFlush = true;
for (int i = 0; i < cmd.Length; i++)
{
p.StandardInput.WriteLine(cmd.ToString());
}
p.StandardInput.WriteLine("exit");
string strRst = p.StandardOutput.ReadToEnd();
p.WaitForExit();
p.Close();
CloseProcess("cmd.exe");//执行结束,关闭cmd进程
return strRst;
}
  结束Process 方法



  /// <summary>
/// 关闭进程
/// </summary>
/// <param name="ProcName">进程名称</param>
/// <returns></returns>
public static bool CloseProcess(string ProcName)
{
bool result = false;
System.Collections.ArrayList procList = new System.Collections.ArrayList();
string tempName = "";
int begpos;
int endpos;
foreach (System.Diagnostics.Process thisProc in System.Diagnostics.Process.GetProcesses())
{
tempName = thisProc.ToString();
begpos = tempName.IndexOf("(") + 1;
endpos = tempName.IndexOf(")");
tempName = tempName.Substring(begpos, endpos - begpos);
procList.Add(tempName);
if (tempName == ProcName)
{
if (!thisProc.CloseMainWindow())
thisProc.Kill(); // 当发送关闭窗口命令无效时强行结束进程
result = true;
}
}
return result;
}
  因为服务的请求可能会从系统服务或者应用程序发起请求,所以我们要加一个完善的主方法请求判断,如果是命令行过来的就给用户提供可选的操作菜单,否则运行服务。
  定义一个枚举,记录不同请求来源。



  /// <summary>
/// 定义程序被启用的几种形式
/// </summary>
public enum appModel
{
/// <summary>
/// 网页启用
/// </summary>
            Web,
/// <summary>
/// 系统服务启用
/// </summary>
            Service,
/// <summary>
/// 窗体程序启用
/// </summary>
            Windows,
/// <summary>
/// 控制台启用
/// </summary>
            Console
}
  主方法内添加状态判断



static void Main(string[] args)
{
appModel mode = AutoDetectAppType();//获取应用程序请求来源
if (mode.Equals(appModel.Console))
{//如果是控制台程序,验证是否对服务操作
Console.WriteLine("选择金销帮后台服务操作");
Console.WriteLine("如需操作请选择,[0]服务状态查询[1]安装服务 [2]卸载服务 [3]启动服务[4]停止服务[5]退出");
var rs = int.Parse(Console.ReadLine());
DoParameter(rs);
}
else if (mode.Equals(appModel.Service))
{
//如果是服务,运行系统服务
                ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MainServer(),
};
ServiceBase.Run(ServicesToRun);
}
}
  根据用户每次选择不同的菜单对Windows服务发出命令



/// <summary>
/// 判断用户输入参数
/// </summary>
/// <param name="rs">控制台输入参数</param>
public static void DoParameter(int rs)
{
//[0]服务状态查询[1]安装服务 [2]卸载服务 [3]启动服务[4]停止服务[5]退出
switch (rs)
{
case 0:
//查询
string back_query = Cmd(new string[] { "sc query  jinxiaobangServices" });//查询服务信息
Console.WriteLine("------------------------------------------------------------------------------------");
Console.WriteLine("查询服务信息如下:\n\n\n " + back_query);//输出查询结果
Console.WriteLine("如需操作请选择,[0]服务状态查询[1]安装服务 [2]卸载服务 [3]启动服务[4]停止服务[5]退出");
Console.WriteLine("------------------------------------------------------------------------------------");
var param_query = int.Parse(Console.ReadLine());
DoParameter(param_query);
break;
case 1:
//安装服务
var path = Process.GetCurrentProcess().MainModule.FileName;
string back_create = Cmd(new string[] { "sc create jinxiaobangServices binpath= \"" + path + "\" displayName= JXBServices start= auto obj= localsystem ", "sc description   \"jinxiaobangServices\"  \"金销帮后台异步通知、数据统计、定时任务等处理\" " });
Console.WriteLine("------------------------------------------------------------------------------------");
Console.WriteLine("安装成功\n\n\n" + back_create);
Console.WriteLine("如需操作请选择,[0]服务状态查询[1]安装服务 [2]卸载服务 [3]启动服务[4]停止服务[5]退出");
Console.WriteLine("------------------------------------------------------------------------------------");
var param_create = int.Parse(Console.ReadLine());
DoParameter(param_create);
break;
case 2:
//卸载服务
string back_delete = Cmd(new string[] { "sc delete  jinxiaobangServices" });//卸载服务
Console.WriteLine("------------------------------------------------------------------------------------");
Console.WriteLine("卸载成功\n\n\n" + back_delete);
Console.WriteLine("如需操作请选择,[0]服务状态查询[1]安装服务 [2]卸载服务 [3]启动服务[4]停止服务[5]退出");
Console.WriteLine("------------------------------------------------------------------------------------");
var param_delete = int.Parse(Console.ReadLine());
DoParameter(param_delete);
break;
case 3:
//启动服务
//Process.Start("sc", "start  jinxiaobangServices");//sc执行命令
string back_start = Cmd(new string[] { "sc start  jinxiaobangServices" });//启动服务
Console.WriteLine("------------------------------------------------------------------------------------");
Console.WriteLine("启动成功\n\n\n" + back_start);
Console.WriteLine("如需操作请选择,[0]服务状态查询[1]安装服务 [2]卸载服务 [3]启动服务[4]停止服务[5]退出");
Console.WriteLine("------------------------------------------------------------------------------------");
var param_start = int.Parse(Console.ReadLine());
DoParameter(param_start);
break;
case 4:
//停止服务
string back_stop = Cmd(new string[] { "sc stop  jinxiaobangServices" });//停止服务
Console.WriteLine("------------------------------------------------------------------------------------");
Console.WriteLine("停止服务\n\n\n" + back_stop);
Console.WriteLine("如需操作请选择,[0]服务状态查询[1]安装服务 [2]卸载服务 [3]启动服务[4]停止服务[5]退出");
Console.WriteLine("------------------------------------------------------------------------------------");
var param_stop = int.Parse(Console.ReadLine());
DoParameter(param_stop);
//退出
break;
case 5:
//退出
break;
}
}
  到这里就把整个服务操作过程了解清楚了,后面就可以准备自己的业务代码。例如服务启动时和停止时分别做一些业务操作



protected override void OnStart(string[] args)
{
// TODO:  在此处添加代码以启动服务。
FileStream fs = new FileStream(@"C:\Windows\JinXBWinServer.log", FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.BaseStream.Seek(0, SeekOrigin.End);
sw.WriteLine("WindowsService: Service Started" + DateTime.Now.ToString() + "\n");
sw.Flush();
sw.Close();
fs.Close();
}
protected override void OnStop()
{
// TODO:  在此处添加代码以执行停止服务所需的关闭操作。
FileStream fs = new FileStream(@"C:\Windows\JinXBWinServer.log", FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.BaseStream.Seek(0, SeekOrigin.End);
sw.WriteLine("WindowsService: Service Stopped" + DateTime.Now.ToString() + "\n");
sw.Flush();
sw.Close();
fs.Close();
}
  可以分别通过OnStart和OnStop去记录一下服务操作记录,来做个测试。
  服务编写完,先别急着F5测试。因为运行权限的问题,这时可能会出现1053:服务没有及时响应启动或控制请求。这是因为VS权限不足,可以在debug文件中用管理员运行测试一下,是不是OK了。
  特别注意:每次更新安装都要用最新的SetUp.exe安装包,点击右键生成可以自动在“SetUp\Express\SingleImage\DiskImages\DISK1\setup.exe”路径下生成exe安装文件,一定记得安装最新版。
  InstallShield Limited Edition for Visual Studio的具体使用,可以网上找一下,也可以参考这里:http://blog.csdn.net/kingmax54212008/article/details/44303539

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-389207-1-1.html 上篇帖子: redis3.0.6安装(linux和windows) 下篇帖子: Windows Server 2012 R2 或 2016 无法安装 .Net 3.5.1
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表