我需要在.NET中编写健壮的代码,以使Windows服务(服务器2003)能够自行重启。这样做的最佳途径是什么?是否有一些.NET API可以做到这一点?
答案 0 :(得分:181)
将服务设置为在失败后重新启动(双击控制面板中的服务并浏览这些选项卡 - 我忘记了它的名称)。然后,只要您希望服务重新启动,只需调用Environment.Exit(1)
(或任何非零返回),操作系统将为您重新启动它。
答案 1 :(得分:22)
Dim proc As New Process()
Dim psi As New ProcessStartInfo()
psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()
答案 2 :(得分:15)
您无法确定您的服务运行的用户帐户是否具有停止和重新启动服务的权限。
答案 3 :(得分:9)
您可以创建一个自动重启的DOS命令提示符进程:
Process process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
process.Start();
答案 4 :(得分:9)
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);
其中SERVICENAME
是您的服务名称(为了说明服务名称中的空格而包含的双引号,否则可以省略)。
清洁,无需自动重启配置。
答案 5 :(得分:5)
这取决于你为什么要重新启动它。
如果您只是想找到一种让服务定期清理的方法,那么您可以在服务中运行一个定期执行清除例程的计时器。
如果您正在寻找一种在失败时重启的方法 - 服务主机本身可以在设置时提供该功能。
那么为什么需要重启服务器呢?你想要实现什么目标?
答案 6 :(得分:3)
我认为你不能在一个自包含的服务中(当你调用Restart时,它将停止服务,这将中断Restart命令,并且它不会再次启动)。如果您可以添加第二个.exe(一个使用ServiceManager类的控制台应用程序),那么您可以启动独立的.exe并重新启动该服务然后退出。
第二个想法,您可能让服务注册一个计划任务(例如,使用命令行'at'命令)来启动服务,然后让它自行停止;这可能会奏效。
答案 7 :(得分:3)
炮轰批处理文件或EXE的问题是服务可能具有也可能没有运行外部应用程序所需的权限。
我发现最简洁的方法是使用OnStop()方法,它是服务控制管理器的入口点。然后,所有清理代码都将运行,并且假设您的停止代码正在执行其工作,您将不会有任何挂起的套接字或其他进程。
要执行此操作,您需要在终止之前设置一个标志,告诉OnStop方法退出并显示错误代码;然后SCM知道该服务需要重新启动。如果没有此标志,您将无法从SCM手动停止服务。这也假设您已设置服务以在错误时重新启动。
这是我的停止代码:
...
bool ABORT;
protected override void OnStop()
{
Logger.log("Stopping service");
WorkThreadRun = false;
WorkThread.Join();
Logger.stop();
// if there was a problem, set an exit error code
// so the service manager will restart this
if(ABORT)Environment.Exit(1);
}
如果服务遇到问题并需要重新启动,我会启动一个从SCM停止服务的线程。这允许服务自行清理:
...
if(NeedToRestart)
{
ABORT = true;
new Thread(RestartThread).Start();
}
void RestartThread()
{
ServiceController sc = new ServiceController(ServiceName);
try
{
sc.Stop();
}
catch (Exception) { }
}
答案 8 :(得分:2)
我会使用Windows Scheduler安排重新启动您的服务。问题是你不能自己重启,但你可以阻止自己。 (你基本上已经把你所在的分支机构锯掉了......如果你得到了我的比喻)你需要一个单独的过程来为你做这件事。 Windows Scheduler是合适的。安排一次性任务以重新启动服务(甚至从服务本身内)以立即执行。
否则,您将必须创建一个“牧羊”流程,为您完成此任务。
答案 9 :(得分:1)
我认为不可以。当服务“停止”时,它将完全卸载。
好吧,好吧,我想总有一种方法。例如,您可以创建一个分离的进程来停止服务,然后重新启动它,然后退出。答案 10 :(得分:1)
创建一个单独的appdomain来托管应用程序代码。当需要重启时,我们可以卸载并重新加载appdomain而不是进程(windows服务)。这就是IIS应用程序池的工作原理,它们不直接运行asp.net应用程序,它们使用单独的appdmain。
答案 11 :(得分:1)
对问题的第一个回答是最简单的解决方案:“Environment.Exit(1)”我在Windows Server 2008 R2上使用它并且它运行良好。服务自行停止,操作系统等待1分钟,然后重新启动它。
答案 12 :(得分:0)
nssm非常好。它会为你做这一切
答案 13 :(得分:0)
像这样创建一个restart.bat文件
@echo on
set once="C:\Program Files\MyService\once.bat"
set taskname=Restart_MyService
set service=MyService
echo rem %time% >%once%
echo net stop %service% >>%once%
echo net start %service% >>%once%
echo del %once% >>%once%
schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z
schtasks /run /tn %taskname%
然后在%service%启动时删除任务%taskname%
答案 14 :(得分:0)
刚刚通过:我想我会添加一些额外的信息......
你也可以抛出异常,这将自动关闭windows服务,并且自动重新启动选项才会启动。唯一的问题是,如果你的电脑上有开发环境,那么JIT会尝试踢进去,你会得到一个提示说调试Y / N.说不,然后它会关闭,然后重新正常启动。 (在没有JIT的PC上,它只是一切正常)。 我拖的原因是,这个JIT是Win 7的新手(它曾经与XP等一起工作)并且我试图找到一种禁用JIT的方法....我可以尝试这里提到的Environment.Exit方法看看如何这也有效。
克里斯蒂安:英国布里斯托尔
答案 15 :(得分:0)
更好的方法可能是将NT服务用作应用程序的包装器。启动NT服务后,您的应用程序可以以“空闲”模式启动,等待命令启动(或配置为自动启动)。
想想一辆汽车,当汽车启动它开始处于空闲状态,等待你的命令前进或后退。这也可以带来其他好处,例如更好的远程管理,因为您可以选择如何公开您的应用程序。
答案 16 :(得分:-2)
最简单的方法是使用批处理文件:
净停止 净开始
并使用所需的时间间隔将文件添加到调度程序
答案 17 :(得分:-3)
private static void RestartService(string serviceName)
{
using (var controller = new ServiceController(serviceName))
{
controller.Stop();
int counter = 0;
while (controller.Status != ServiceControllerStatus.Stopped)
{
Thread.Sleep(100);
controller.Refresh();
counter++;
if (counter > 1000)
{
throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName));
}
}
controller.Start();
}
}