背景介绍:

C#IISRESET服务终结版_C# 远程IISRESET

实现如上图所示的,页面一键控制服务器IISRESET


服务器上部署了EnvAgency这个Service来接受请求并处理以及返回,但是IISRESET这个请求特殊,因为IISRESET后会重启程序池,包括EnvAgency程序,就不能返回IISRESET请求的具体结果,但是IISRESET的单次成功率不高,又后果失败影响大,所以必须保证IISRESET的成功。试过很多中方法,具体尝试方法记录于http://4453154.blog.51cto.com/4443154/1689318,某些情况下,这些方法是可行的。但是我这边由于严格的域帐号机器帐号控制导致不可行。所以换了如下方法:

C#IISRESET服务终结版_C# 远程IISRESET_02

环境系统调用服务器上代理,代理触发服务器上IISRESET的应用,该应用会启动iisreset并且读取返回,如果返回是正确的,就退出,否则继续调用iisreset,这样就确保多次后iis启动成功。由于IISRESET应用是写成Console程序,不受IIS程序池影响。并且加入Nlog来记录相应信息,方便出问题后排查。


在判断iis启动成功方面:采用循环5秒请求下服务器时间,看服务器是否有反应来判断启动是否成功。


应用存放目录:

D:\\websites\\EnvCmd\\cmdtest


IISRESET的应用配置具体代码如下:

using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cmdtest
{
    public class ProcessUtil
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        public static bool IISReset()
        {
            Logger.Info("Start IISRESET");
            int flag = 0;
            string output = IISResetProcess();
            Logger.Info(output);
            string regx = "正在尝试停止...\r\r\nInternet 服务已成功停止\r\r\n正在尝试启动...\r\r\nInternet 服务已成功启动";
            while (flag < 10 && !output.Contains(regx))
            {
                output = IISResetProcess();
                Logger.Info(output);
                flag++;
            }
            bool result = output.Contains(regx);
            Logger.Info("Finish IISRESET - result : " + result);
            return result;
        }
        public static string IISResetProcess()
        {
            Process pro = new Process();
            // 设置命令行、参数
            pro.StartInfo.FileName = "cmd.exe";
            pro.StartInfo.UseShellExecute = false;
            pro.StartInfo.RedirectStandardInput = true;
            pro.StartInfo.RedirectStandardOutput = true;
            pro.StartInfo.RedirectStandardError = true;
            pro.StartInfo.CreateNoWindow = true;
            // 启动CMD
            pro.Start();
            // 运行端口检查命令
            pro.StandardInput.WriteLine("iisreset");
            pro.StandardInput.WriteLine("exit");
            return pro.StandardOutput.ReadToEnd();
        }
    }
}
using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cmdtest
{
    class Program
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        static void Main(string[] args)
        {
            Logger.Info("test");
            Console.WriteLine(ProcessUtil.IISReset());
        }
    }
}


服务器代理EvnAgency中IISReset调用如下: 

public JsonResult IISReset(PostPackBase pack)
        {
            var resp = new APIResponse<string>()
            {
                StateCode = StateCode.Success,
                Message = ""
            };
            var accessToken = LoginSecurity.DecodeAccessToken(pack.Token);
            if (accessToken == null)
            {
                resp.StateCode = StateCode.Fail;
                resp.Message = "操作用户无法识别!";
            }
            else if (accessToken.ExpiredTime < DateTime.Now)
            {
                resp.StateCode = StateCode.Fail;
                resp.Message = "登陆信息过期!";
            }
            else
            {               
                try
                {
                    var token = LoginSecurity.DecodeAccessToken(pack.Token);
                    EnvMachine envmachine = EnvMachineBiz.GetCurrentMachine();
                    string ip = envmachine.IP;
                    Logger.Info("IISReset start by " + token.Alias + " on " + ip);
                    string str = string.Format("{0} Reset IIS on {1} ", token.Alias, ip) ;
                    EnvOperationLogBiz.LogOptIISReset(envmachine.EnvSubId, token.Alias, str, envmachine.Id);
                    IISUtil.IISReset();                  
                }
                catch (Exception ex)
                {
                    resp.StateCode = StateCode.Fail;
                    resp.Message += ex.ToString();
                    Logger.ErrorException("IISReset status result : Exception, " + ex.ToString(), ex);
                }             
            }
            return Json(resp, JsonRequestBehavior.DenyGet);
        }


具体调用应用程序代码如下:

public static void IISReset()
        {
            Logger.Info("Start D:\\websites\\EnvCmd\\cmdtest");
            Process.Start("D:\\websites\\EnvCmd\\cmdtest");
        }


环境管理系统中前端代码如下:

html代码如下

<li><a onclick="javascript: pageui.render('iisreset')">IIS Reset</a></li>


js代码如下

////// 主页面 //////
pageui = {
    render: function (pageType) {
        var page;
        if (pageType == 'iisreset') {
            page = iisresetpage;
        }       
        page.render();
    }
};
var iisresetpage = {
    render: function () {
       
        var container = $(pageid.mainContent);
        container.empty();
        chcoreui.attachLoader(container, pageid.loader, 410, 100);
        var url = '/IIS/GetAllMachines';
        var pack = new Object();
        pack.Token = $.readCookie('accessToken');
        var submitData = JSON.stringify(pack);
        $.ajax({
            type: "POST",
            url: url,
            data: submitData,
            dataType: "json",
            contentType: "application/json",
            crossDomain: true,
            success: function (results) {
                if (results.StateCode == 0) {
                    // 成功
                    var bodyContent = '';
                    $.each(results.Data, function (idx, item) {
                        bodyContent += '<tr><td style="text-align:center;"><button class="link iisresetbtn"><i class="icon-play"></i></button></td><td>' + item.MachineName + '</td><td>' + item.IPAddress + '</td><td style="text-align:center;">' + item.DomainName + '</td><td><button class="link logbtn"><span class="mif-loop2"></span>日志</button></td></tr>';
                    });
                    
                    container.empty();
                    container.html('<table class="table bordered striped hovered dataTable" cellspacing="0" id="apppooltable"><thead><tr><th><button class="resetallbtn warning"><i class="icon-play on-left"></i>重启IIS</button></th><th>机器名</th><th>IP地址</th><th>环境名称</th><th>Actions</th></tr></thead><tbody>' + bodyContent + '</tbody></table>');
                    $('#apppooltable').dataTable({
                        "paging": false,
                        "searching": true,
                        "ordering": true,
                        "info": "程序池信息表",
                        // "scrollY": "450px",
                        "scrollCollapse": true,
                        "dom": '<"tool1bar">fr1tip'
                    });
                    $(".iisresetbtn").click(function () {
                        iisresetpage.startReset($(this));
                    });
                    
                    $(".resetallbtn").click(function () {
                        if (!$(this).hasClass('disabled')) {
                            var syncbtns = $('.iisresetbtn');
                            $(this).addClass('disabled');
                            $.each(syncbtns, function (idx, item) {
                                item.click();
                            });
                        }
                    });
                    $(".logbtn").click(function () {
                        iisresetpage.getResetLog($(this));
                    });
                    
                }
            },
            error: function (xhr, status, error) {
                $.note('Error', '获取程序池信息失败,请联系管理员.', 'error');
            }
        });
    },
    startReset: function (sender) {
        var parentObj = sender.parent();
        var ip = parentObj.next().next().text();
        iisresetpage.postReset(ip, sender);
    },
    postReset:function(ip,sender)
    {
        var parentObj = sender.parent();
        parentObj.empty();
        parentObj.append('<img src="../img/loading.jpg" style="width:30px;" id="iloader" />');
        commonajax.postIISReset(ip);
        var flag = 0;
       
        iisresetpage.checkPostResult(ip, parentObj,flag);
     
    },
    checkPostResult: function (ip, parentObj, flag)
    {
         setTimeout(
           function () {
               var result = commonajax.pingServerTime(ip, function () {
                   parentObj.empty();
                   $.note(null, ip + 'IISReset成功!');
                   parentObj.append('<button class="link resetsuccessbtn" style="margin-left:30px;"><i class="icon-checkmark fg-green" style="margin-left:45px;"></i></button>');
                   $('.resetsuccessbtn').click(function () {
                       iisresetpage.startReset($(this));
                   });                  
               }, function () {
                   if (flag > 10) {
                       $.note('Error', ip + 'IISReset失败!请联系管理员处理!', 'error');
                       parentObj.append('<button class="link resetfailbtn" style="margin-left:30px;"><i class="icon-cancel-2 fg-red"></i></button>');
                       $('.resetfailbtn').click(function () {
                           iisresetpage.startReset($(this));
                       });                  
                   }
                   else {
                       checkPostResult(ip, parentObj, ++flag);
                   }
               });
              
           }, 5000);
    },
   
    getResetLog: function (sender) {
        debugger;
        var parentObj = sender.parent();
        var ip = parentObj.prev().prev().text();
        var url = '/IIS/GetIISResetLog';
        $.Dialog({
            overlay: true,
            shadow: true,
            flat: true,
            icon: null,
            title: '日志',
            content: null,
            onShow: function (_dialog) {
                var content = _dialog.children('.content');
                content.html('<div style="margin:15px; width:900px;height:500px;OVERFLOW: auto;" id="ilogcontainer"></div>');
                chcoreui.attachLoader($('#ilogcontainer'), pageid.loader, 410, 130);
                // 准备提交数据
                var pack = new Object();
                pack.ip = ip
                pack.time = "1";
                pack.Token = $.readCookie('accessToken');
                var submitData = JSON.stringify(pack);
                $.ajax({
                    type: "POST",
                    url: url,
                    data: submitData,
                    dataType: "json",
                    contentType: "application/json",
                    crossDomain: true,
                    success: function (data) {
                        if (data.StateCode == 0) {
                            var bodyContent = '';
                            $.each(data.Data, function (idx, item) {
                                bodyContent += '<tr><td style="text-align:center">' + item.Id + '</td><td style="text-align:center">' + $.convertToDateStr(item.OpTime) + '</td><td style="text-align:center">' + item.OpAlias + '</td><td>' + item.Des + '</td></tr>';
                            });
                            $('#ilogcontainer').empty();
                            $('#ilogcontainer').html('<table class="table bordered striped hovered dataTable" cellspacing="0" id="ilogtable"><thead><tr><th>编号</th><th>操作日期</th><th>操作人</th><th>内容</th></tr></thead><tbody>' + bodyContent + '</tbody></table>');
                            $('#ilogtable').dataTable({
                                "paging": true,
                                "searching": false,
                                "ordering": false,
                                "info": false,
                                "dom": '<"tool1bar">fr1tip'
                            });
                        }
                    },
                    error: function (xhr, status, error) {
                        $.note(null, "获取IISRest日志失败!", "error");
                    }
                });
            }
         });
    }
};
var commonajax = {
    // Ping服务器时间
    pingServerTime: function (ip,successcallback,failcallback) {
        var url = 'http://' + ip + ':8167/Monitor/Ping';
        $.ajax({
            type: "POST",
            url: url,
            dataType: "json",
            contentType: "application/json",
            crossDomain: true,
            success: function (results) {
                var reg = /\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}/;
                if (reg.test(results)) {
                    successcallback();
                }
                else {
                    failcallback();
                }
            }
        });
    },
    postIISReset: function (ip) {
        var url = 'http://' + ip + ':8167/IIS/IISReset';
        // 准备提交数据
        var pack = new Object();
        pack.Token = $.readCookie('accessToken');
        var submitData = JSON.stringify(pack);
        $.ajax({
            type: "POST",
            url: url,
            data: submitData,
            dataType: "json",
            contentType: "application/json",
            crossDomain: true,
            success: function (results) { },
            error: function (xhr, status, error) { }
        });
    }
}


至此,完美实现,可靠的IISRESET功能。